结合上一篇同步异步,这篇理解线程操作。

1、新建线程。不止thread和runnable,Callable和Future了解一下

package com.thread;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask; /**
* 线程启动
* @author Administrator
*
*/
public class StartThreadTest extends Thread{ @Override
public void run(){
for (int i = 0; i < 3; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"i:"+i);
}
} public static void main(String[] args) throws InterruptedException {
//继承 Thread 类的线程启动方式
StartThreadTest test = new StartThreadTest();
StartThreadTest test2 = new StartThreadTest();
System.out.println("开始执行线程1......");
test.start();test2.start();
test.join();test2.join(); //join方法会让main线程等待test、test2线程执行完,如果对执行结果不感冒,则不用join
System.out.println("结束执行线程1......");
}
//******************************************************************************************************
static class startThread2 implements Runnable{ @Override
public void run() {
for (int i = 0; i < 3; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i:"+i);
}
} public static void main(String[] args) {
//实现 Runnable 接口的线程启动方式
startThread2 thread2 = new startThread2();
Thread t = new Thread(thread2);
t.start();
}
}
//******************************************************************************************************
/**
* Callable 用于获取线程执行结果
* 多个Callable耗时是每个线程的总耗时
* @author Administrator
*
*/
static class startThread3 implements Callable<String>{ @Override
public String call() throws Exception {
int result = 0;
for (int i = 0; i < 3; i++) {
Thread.sleep(1000);
result += i;
}
return String.valueOf(result);
} public static void main(String[] args) throws Exception {
SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
System.out.println("开始时间:"+format.format(new Date())); Callable<String> call = new Callable<String>() { @Override
public String call() throws Exception {
int result = 0;
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
result += i;
}
return String.valueOf(result);
}
};
ExecutorService service = Executors.newSingleThreadExecutor();
Future<String> f = service.submit(call);
System.out.println(f.get());
service.shutdown();
System.out.println("时间1:"+format.format(new Date()));
//实现 Callable 接口的线程启动方式
startThread3 thread3 = new startThread3();
System.out.println("开始执行线程......");
String result = thread3.call();
System.out.println("结束执行线程。result:"+result); //result:3 【线程执行完获取结果,会阻塞当前线程】
System.out.println("时间2:"+format.format(new Date())); //开始时间:05:04:21
//10
//时间1:05:04:26
//开始执行线程......
//结束执行线程。result:3
//时间2:05:04:29 }
}
//******************************************************************************************************
/**
* Future 用于获取异步线程的结果,总耗时是最长耗时的线程
* @author Administrator
*
*/
static class startThread4 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
System.out.println("开始时间:"+format.format(new Date())); //操作1:耗时3秒
FutureTask<String> futureTask = new FutureTask<>(new startThread3());
new Thread(futureTask).start(); //操作2:耗时5秒
Callable<String> call = new Callable<String>() { @Override
public String call() throws Exception {
int result = 0;
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
result += i;
}
return String.valueOf(result);
}
};
FutureTask<String> futureTask2 = new FutureTask<>(call);
new Thread(futureTask2).start(); System.out.println("操作1返回:"+futureTask.get());
System.out.println("操作2返回:"+futureTask2.get()); System.out.println("结束时间:"+format.format(new Date())); //开始时间:04:50:53
//操作1返回:3
//操作2返回:10
//结束时间:04:50:58
}
}
}

2、停止线程。volatile和interrupt各显神通

package com.thread;

import java.text.SimpleDateFormat;
import java.util.Date; /**
* 关闭线程
* @author Administrator
*
*/
public class StopThreadTest extends Thread { static int i = 0;
static int j = 0; @Override
public void run() {
//同步操作确保i,j都自增1
synchronized (this) {
i++;
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
j++;
}
} public static void main(String[] args) throws InterruptedException {
StopThreadTest test = new StopThreadTest();
test.start();
Thread.sleep(1000);
//Thread.stop():强制关闭对象获取的锁,破坏线程数据安全
test.stop();
test.join();
System.out.println("i:"+i+";j:"+j); //i:1;j:0 } static class volatileStopThreadTest extends Thread{ volatile boolean exitFlag = false; //volatile确保可见性
static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss"); @Override
public void run() {
System.out.println("run线程开始时间:"+format.format(new Date()));
while(!exitFlag){
System.out.println("run方法进入时间:"+format.format(new Date()));
//同步操作确保i,j都自增1
synchronized (this) {
i++;
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
j++;
}
}
System.out.println("run线程结束时间:"+format.format(new Date()));
} public static void main(String[] args) throws InterruptedException {
System.out.println("主线程开始时间:"+format.format(new Date()));
volatileStopThreadTest test = new volatileStopThreadTest();
test.start();
Thread.sleep(1000);
System.out.println("主线程休眠1秒:"+format.format(new Date()));
test.exitFlag = true;
test.join();
System.out.println("i:"+i+";j:"+j); //主线程开始时间:05:17:03
//run线程开始时间:05:17:03
//run方法进入时间:05:17:03
//主线程休眠1秒:05:17:04 【标志位exitFlag改了,run方法依然在执行,只是下次竞争到锁都不执行run】
//run线程结束时间:05:17:13
//i:1;j:1 【确保了线程数据安全】 }
} static class interruptStopThreadTest extends Thread{ static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss"); @Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-线程进入run开始时间:"+format.format(new Date()));
while(true){
//判断线程是否已经被中断,如果被中断,则下次竞争时直接退出
if(Thread.currentThread().isInterrupted()){
System.out.println(Thread.currentThread().getName()+"-线程已被中断......,中断时间:"+format.format(new Date()));
//退出while循环
break;
}
//同步操作确保i,j都自增1
synchronized (this) {
i++;
try {
Thread.sleep(10000);
System.out.println(Thread.currentThread().getName()+"-线程休眠10秒......");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("中断标志:"+Thread.currentThread().isInterrupted());
//阻塞过程中被中断,test.interrupt()方法设置的中断标识会立刻变成false,需要重新设置中断标识
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().getName()+"-线程被中断了!");
}
j++;
}
//打印:
//Thread-0-线程进入run开始时间:10:01:34
//java.lang.InterruptedException: sleep interrupted
// at java.lang.Thread.sleep(Native Method)
// at com.thread.StopThreadTest$interruptStopThreadTest.run(StopThreadTest.java:103)
//中断标志:false
//Thread-0-线程被中断了!
//Thread-0-线程已被中断......,中断时间:10:01:36
//i:1;j:1 【线程数据安全】 // synchronized (this) {
// i++;
// try {
// for (int z = 0; z < 10; z++) {
// if(z==9){
// int a = 1/0;
// System.out.println("模拟异常");
// }
// }
// Thread.sleep(5000); //异常后的语句不会执行
// } catch (Exception e) {
// e.printStackTrace();
// //线程执行过程中抛出了异常,通过设置中断标识,控制下次竞争
// Thread.currentThread().interrupt();
// System.out.println(Thread.currentThread().getName()+"-线程被中断了!");
// }
// j++;
// }
//打印:
//Thread-0-线程进入run开始时间:10:08:43
//Thread-0-线程被中断了!
//java.lang.ArithmeticException: / by zeroThread-0-线程已被中断......,中断时间:10:08:43 // at com.thread.StopThreadTest$interruptStopThreadTest.run(StopThreadTest.java:126)
//i:1;j:1 【线程数据安全】 }
} public static void main(String[] args) throws InterruptedException {
interruptStopThreadTest test = new interruptStopThreadTest();
test.start();
Thread.sleep(2000);
test.interrupt(); //中断线程 【设置中断标志,通过isInterrupted()控制竞争】
test.join();
System.out.println("i:"+i+";j:"+j);
}
}
}

3、线程挂起和继续执行。suspend和resume谨慎使用

package com.thread;

/**
* 线程挂起与继续执行
* 不推荐用:
* 1、锁得不到释放,如果第二个线程先于第一个线程执行resume之前执行start,将造成锁永久等待
* 2、锁住的共享资源如果暗含同步方法,将导致其他线程使用该同步方法等待
* @author Administrator
*
*/
public class SuspendANDresumeThreadTest extends Thread{ volatile int i = 0; @Override
public void run(){
while(true){
synchronized(this){
i++;
System.out.println(Thread.currentThread().getName()+"-i:"+i);
}
}
} public static void main(String[] args) throws InterruptedException {
SuspendANDresumeThreadTest test = new SuspendANDresumeThreadTest();
SuspendANDresumeThreadTest test2 = new SuspendANDresumeThreadTest();
test.start();
Thread.sleep(1);
//test线程挂起后,占有的锁不会释放,导致test2线程一直处于阻塞态
test.suspend();
// test2.start();
// test.join();
//另外:查看println源码得知该方法是同步方法,在test占有锁的同时,导致println()也被占有,从而main线程无法执行下面的打印语句
System.out.println("该句无法打印!"); }
}

4、等待线程结束和谦让。join和yield

package com.thread;

import java.text.SimpleDateFormat;
import java.util.Date; /**
* join:当前线程等待执行join的线程执行完
* yield:执行yield的线程让出占用的锁
* @author Administrator
*
*/
public class JoinANDyieldThreadTest extends Thread{ static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss"); @Override
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"-i:"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) throws InterruptedException {
JoinANDyieldThreadTest test = new JoinANDyieldThreadTest();
JoinANDyieldThreadTest test2 = new JoinANDyieldThreadTest(); // test.start();
// Thread.sleep(3000);
// test.yield();
// test2.start(); //Thread-0-i:0
//Thread-0-i:1
//Thread-0-i:2
//Thread-0-i:3 【执行test.yield()后,test依然抢到了锁】
//Thread-1-i:0
//Thread-1-i:1
//Thread-0-i:4 test.setPriority(MIN_PRIORITY); //低优先级
test2.setPriority(MAX_PRIORITY); //高优先级
System.out.println("开始时间:"+format.format(new Date()));
test.start();
Thread.sleep(3000);
test.yield();
test2.start();
test.join();
test2.join(); //确保下面的打印在test和test2执行完后执行
System.out.println("结束时间:"+format.format(new Date()));
//Thread-0-i:0
//Thread-0-i:1
//Thread-0-i:2
//Thread-0-i:3 【test设置低优先级依然抢到了锁】
//Thread-1-i:0
//Thread-0-i:4
//Thread-1-i:1
//Thread-0-i:5 }
}

5、线程等待和唤醒。wait和notify

package com.thread;

/**
* wait 和 notify 设计生产者与消费者模式
* 锁的选用:线程共享的变量
* wait 和 notify时机的运用,确保先生产后消费
* @author Administrator
*
*/
public class WaitANDnotifyThreadTest {
private static Integer count = 0; // 数据仓库计数
private final static Integer FULL = 5; // 数据仓库最大存储量
private static String lock = "lock"; // 锁标识
// Object obj = new Object(); //锁标识 public static void main(String[] args) {
new Thread(new Producer(), "product1").start();
new Thread(new Consumer(), "consumer1").start();
new Thread(new Producer(), "product2").start();
new Thread(new Consumer(), "consumer2").start();
} // 生产者
static class Producer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized (lock) {
while (count == FULL) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
System.out.println(Thread.currentThread().getName() + "-produce:: " + count);
// 唤醒lock锁上的所有线程
lock.notifyAll();
}
}
}
} // 消费者
static class Consumer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized (lock) {
// 如果首次消费者竞争得到锁,进入后等待
while (count == 0) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println(Thread.currentThread().getName() + "-consume:: " + count);
lock.notifyAll();
}
}
}
}
}

Java高并发之线程基本操作的更多相关文章

  1. java高并发之线程池

    Java高并发之线程池详解   线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对 ...

  2. 1.6 JAVA高并发之线程池

    一.JAVA高级并发 1.5JDK之后引入高级并发特性,大多数的特性在java.util.concurrent 包中,是专门用于多线程发编程的,充分利用了现代多处理器和多核心系统的功能以编写大规模并发 ...

  3. Java高并发之线程池详解

    线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对象, 那么系统效率将大大提升. ...

  4. Java高并发之锁优化

    本文主要讲并行优化的几种方式, 其结构如下: 锁优化 减少锁的持有时间 例如避免给整个方法加锁 public synchronized void syncMethod(){ othercode1(); ...

  5. java高并发之锁的使用以及原理浅析

    锁像synchronized同步块一样,是一种线程同步机制.让自Java 5开始,java.util.concurrent.locks包提供了另一种方式实现线程同步机制——Lock.那么问题来了既然都 ...

  6. Java高并发之无锁与Atomic源码分析

    目录 CAS原理 AtomicInteger Unsafe AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntege ...

  7. Java高并发之设计模式

    本文主要讲解几种常见并行模式, 具体目录结构如下图. 单例 单例是最常见的一种设计模式, 一般用于全局对象管理, 比如xml配置读写之类的. 一般分为懒汉式, 饿汉式. 懒汉式: 方法上加synchr ...

  8. Java高并发之同步异步

    1.概念理解: 2.同步的解决方案: 1).基于代码 synchronized 关键字 修饰普通方法:作用于当前实例加锁,进入同步代码前要获得当前实例的锁. 修饰静态方法:作用于当前类对象加锁,进入同 ...

  9. Java 高并发之魂

    前置知识 了解Java基本语法 了解多线程基本知识 知识介绍 Synchronized简介:作用.地位.不控制并发的后果 两种用法:对象锁和类锁 多线程访问同步方法的7种情况:是否是static.Sy ...

随机推荐

  1. 用java实现删除文件夹里的所有文件

    package com.org.improve.contact; import java.io.File; public class DeletePaper { /** * @param args * ...

  2. 如何使用rem单位

    最近搞移动端,真是被rem.em与px的换算要了老命了,看了不少文档,似乎弄明白了,这不今天用又蒙圈了. 好多文档上老是说用rem就给html设置font-size,用em就给body设置font-s ...

  3. FormCollection的用法

    FormCollection的用法: 有时候前台抛来的字段太多,在后台一个一个例举出来显得麻烦,而且还容易出错,FormCollection解决了这个烦恼 #region 给商家留言 [HttpPos ...

  4. Axis Java调C# Webservice

    这是一个痛苦的过程,如果java对java的webservice可以说很方便,很简单,Axis,CXF等一系列框架生成客户端直接传参调用即可,但是异构语言就有点麻烦了,生成的客户端不好使......无 ...

  5. ORACLE:毫秒与日期的相互转换,获取某天的信息

    毫秒转换为日期 SELECT TO_CHAR(1406538765000 / (1000 * 60 * 60 * 24) + TO_DATE('1970-01-01 08:00:00', 'YYYY- ...

  6. SQLServer:执行计划

    http://www.cnblogs.com/kissdodog/category/532309.html

  7. vos设置可呼出手机或固话

    问题: 默认公司只让呼出手机号码,但有的客户要求能打固话,怎么办? 落地网关——补充设置——落地前缀——落地被叫改写规则 在改写规则里添加固话号段即可 具体案例: 5201——1表示让520号段只能拨 ...

  8. 洛谷 P2251 质量检测

    题目背景 无 题目描述 为了检测生产流水线上总共N件产品的质量,我们首先给每一件产品打一个分数A表示其品质,然后统计前M件产品中质量最差的产品的分值Q[m] = min{A1, A2, ... Am} ...

  9. 【2017-07-04】Qt信号与槽深入理解之一:信号与槽的连接方式

    今天是个好日子,嗯. 信号槽机制是Qt的特色功能之一,类似于windows中的消息机制,在不同的类对象间传递消息时我们经常使用信号槽机制,然而很多时候都没有去关注connect()函数到底有几种重载的 ...

  10. 【BZOJ1067】[SCOI2007] 降雨量(RMQ+分类讨论)

    点此看题面 大致题意:请你判断"\(x\)年是自\(y\)年以来降雨量最多的"这句话的真假. 离散化/\(lower\_bound\) 首先,考虑到年份的范围非常大,便可以离散化. ...