new Thread()和start()
public class Test4 {
public static void main(String[] args) {
//t和main同时并发并行执行,但因为main线程正在运行态执行代码,很快执行后续代码
//打印main和t,本来应该乱序随机,但是先打印main概率上非常高
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t");
}
});//申请系统创建线程t
t.start();//申请系统执行线程t:创建态转变为就绪态,由系统决定什么时候转变为运行态
System.out.println("main");
}
}
实例分析: 我是一个老师(main线程),我正在上课(打印main),然后银行打电话让我去办理一下某个业务,但是我又不能离开,此时我就将这个任务委托一个代理公司,这个代理公司就是另一个线程(Thread t=new Thread),t.start()就是告诉代理公司可以派人帮我去处理了,CPU就去调度执行但至于什么时候执行就看CPU,等价于代理公司派某个员工由代理公司决定,打印t就是最后派人帮我完成了
join()
public class Test4 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t");
}
});
t.start();
t.join();//当前线程main线程无条件等待,直到t线程执行完毕,当前线程再往后执行
System.out.println("main");
}
}
实例分析: 我是一个老师(main线程),我正在上课(main线程运行,打印main),然后银行打电话让我去办理一下某个业务,但是我又不能离开,此时我就将这个任务委托一个代理公司,这个代理公司就是另一个线程(Thread t=new Thread),t.start()就是告诉代理公司可以派人帮我去处理了,CPU就去调度执行但至于什么时候执行就看CPU,等价于代理公司派某个员工由代理公司决定,t.join()让当前线程执行完再去执行main线程(等价于我必须等代理公司派人帮我银行的业务办理完毕之后我才能继续上课),最后再打印main(最后我在把课上完)
interrupt()
public class Test4 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t");
}
});
t.start();
t.join();//当前线程main线程无条件等待,直到t线程执行完毕,当前线程再往后执行
t.interrupt();
System.out.println("main");
}
}
实例分析: 我是一个老师(main线程),我正在上课(main线程运行,打印main),然后银行打电话让我去办理一下某个业务,但是我又不能离开,此时我就将这个任务委托一个代理公司,这个代理公司就是另一个线程(Thread t=new Thread),t.start()就是告诉代理公司可以派人帮我去处理了,CPU就去调度执行但至于什么时候执行就看CPU,等价于代理公司派某个员工由代理公司决定,t.join()让当前线程执行完再去执行main线程(等价于我必须等代理公司派人帮我银行的业务办理完毕之后我才能继续上课),t.interrupt()通知线程中断,至于是否中断自己代码逻辑实现(等价于我通知这个伴我办事的员工先暂停。但是至于是否暂停取决于他自己,好比将在外君命有所不受),最后再打印main(最后我在把课上完)
synchronized
public class Test5 {
private static int COUNT=50;
public static void main(String[] args) throws InterruptedException {
Thread[] threads=new Thread[3];
for(int i=0;i<3;i++){
threads[i]=new Thread(new Runnable() {
@Override
public void run() {
//这里不能加锁:否则那么就只有一个线程始终占着执行完
while (COUNT > 0) {
synchronized (Test5.class) {
/* if(COUNT>0){
COUNT--;
}*/
COUNT--;
System.out.printf("%s: count=%s\n",
Thread.currentThread().getName(), COUNT);
}
}
}
});
}
for (Thread t:threads){
t.start();
}
for (Thread t:threads){
t.join();
}
System.out.println(COUNT);
}
}
使用前提:共享变量操作(静态变量就是共享)
实例分析: COUNT就比作快递数量,main线程就像快递公司,while(COUNT>0)满足原子性不用加锁,COUNT–不具有原子性(这句代码分三步1. 从主存拷贝到工作内存,2.COUNT=COUNT-1修改3.将COUNT写回主存),加锁保证了原子性
volatile
- 保证可见性
- 禁止指令重排序
- 不保证原子性