Java并发编程之美(java并发编程基础篇)
并发编程线程基础
什么是线程
线程是CPU调度的最⼩单位。是进程的组成部分,⼀个进程⾄少包含⼀个线程
线程的创建与运⾏
java创建线程的⽅式jdk提供了3种⽅式,这⾥不包括线程池创建
1. 继承Thread类,并且重写Thread的run⽅法,实例化Thread对象 并且运⾏线程的start⽅法
java编程开发高清pdfclass ThreadOne extends Thread{
@Override
public void run(){
for(;;){
System.out.println("running");
}
}
}
public static void main(String[] args){
Thread one =new ThreadOne();
one.start();
}
2. 实现Runnable接⼝,重写run⽅法,创建Thread对象并且将实现Runnable接⼝的实例传⼊Thread的构造函数
class ThreadTwo implements Runnable{
@Override
public void run(){
for(;;){
System.out.println("running");
}
}
}
public static void main(String[] args){
Thread two =new Thread(new ThreadTwo());
two.start();
}
3.实现Callable接⼝,并且从写call⽅法,创建FutureTask对象 ,将实现Callable接⼝的线程传⼊Futur
eTask的构造函数,再创建Thread对象,将FutureTask对象传⼊Thread的构造函数,运⾏Thread的start⽅法
class ThreadThree implements Callable<String>{
@Override
public String call()throws Exception {
System.out.println("running");
return"running";
}
}
public static void main(String[] args){
FutureTask<String> futureTask =new FutureTask<>(new ThreadThree());
Thread three =new Thread(futureTask);
three.start();
}
实现Callable接⼝与另外2种不同的是,该线程可以拥有返回值 ,在实现接⼝的时候可以传⼊泛型指定改线程的返回值。然后再调
⽤()获取返回值,如果没有线程没有执⾏完毕 那么获取改线程接⼝的线程会阻塞等待
线程通知与运⾏
线程的通知notify与notifyAll,wait⽅法,
1. 线程的运⾏(run⽅法)
当线程被创建,调⽤线程的start()⽅法及运⾏,注意这⾥的运⾏并不是线程执⾏,⽽是处于就绪状态,必须等到它拿到CPU的执⾏权才能真正运⾏。
2. 线程的等待(wait⽅法)
wait与 notify和notifyAll⽅法是 Object的⽅法, ⽽Object是所有类的⽗类。并不是线程的⽅法,所以再使
⽤wait以及notity等⽅法的时候,必须获取到这个对象的监视器锁,⽽这个监视器锁的获取⽅法就是使⽤synchronized关键字获取这个Object的锁
当调⽤object的wait⽅法⽽没有获取锁的时候,就会抛出IllegalMonitorStateException异常
public static void main(String[] args){
Object object =new Object();
try{
object.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
Exception in thread "main" java.lang.IllegalMonitorStateException
//正确⽅式
Object object =new Object();
try{
synchronized(object){
object.wait();
}
}catch(InterruptedException e){
e.printStackTrace();
}
调⽤wait⽅法会让当前线程处于WAIT状态,当其他线程调⽤对象锁对象的notify或者notifyAll⽅法。notify⽅法与notifyAll⽅法的不同在于notify只会唤醒⼀个等待种的线程 ⽽具体唤醒哪⼀个线程取决于哪个线程抢占到了CPU的执⾏权 所以说synchronized是⼀个⾮公平锁,它不能保证先进⼊等待状态的线
程先被唤醒。
public class TestWait {
public static void main(String[] args)throws InterruptedException {
Object object =new Object();
new Thread(()->{
synchronized(object){
try{
System.out.println("线程⼀进⼊等待");
object.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("线程⼀执⾏完毕");
}
}).start();
new Thread(()->{
synchronized(object){
try{
System.out.println("线程⼆进⼊等待");
object.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("线程⼆执⾏完毕");
}
}).start();
new Thread(()->{
synchronized(object){
try{
System.out.println("线程三进⼊等待");
object.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("线程三执⾏完毕");
}
}).start();
Thread.sleep(2000);
synchronized(object){
}
}
}
启动了3个线程。3个线程获取到监视器锁之后 都进⼊了等待 同时说明了 wait⽅法会释放它得到的锁
对象 从⽽别的⽽线程会获取到锁,进⼊等待状态,主线程睡眠2秒后,获取到锁对象,调⽤notify⽅法,唤醒等待3个线程中的其中⼀个。
线程⼀进⼊等待
线程⼆进⼊等待
线程三进⼊等待
线程⼀执⾏完毕
然⽽线程并未结束,因为还有线程⼆和线程三处于等待状态。
synchronized(object){
}
线程⼀进⼊等待
线程⼆进⼊等待
线程三进⼊等待
线程三执⾏完毕
线程⼆执⾏完毕
线程⼀执⾏完毕
notifyAll⽅法会拥有改锁对象的所有等待线程。
wait⽅法还拥有⼀个参数,
public final native void wait(long timeout)throws InterruptedException;
该⽅法传⼊⼀个超时时间 单位为毫秒。表⽰该线程最多等待timeout的时间,如果没有被其他线程唤醒,那么就再timeout后重新进⼊cpu 执⾏权的抢占。
当然再wait的时候,是可以被其他线程打断的,
Thread thread =new Thread(()->{
synchronized(object){
try{
System.out.println("线程三进⼊等待");
object.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("线程三执⾏完毕");
}
});
thread.start();
Thread.sleep(2000);
thread.interrupt();
线程thread运⾏后获取监视器锁后,进⼊等待。主线程睡眠2秒后 执⾏线程的thread的 interrupr⽅法 ,那么该线程也是会被终⽌的。
线程三进⼊等待
java.lang.InterruptedException
线程三执⾏完毕
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.iron.man.TestWait.lambda$main$2(TestWait.java:44)
at java.lang.Thread.run(Thread.java:748)
Process finished with exit code 0
等待线程执⾏终⽌的join⽅法
再实际运⽤中往往会出现⼀个需求,⽅法⼀和⽅法⼆再运⾏,必须等待他们运⾏结束后 再运⾏⽅法三,这时候就需要使⽤join⽅法。join⽅法是线程的⽅法,表⽰调⽤join⽅法的线程执⾏完毕之后 才能继续执⾏其他的线程。
让线程睡眠的sleep⽅法
让出CPU执⾏权的yield⽅法
线程中断
理解线程上下⽂切换
线程死锁
ThreadLocal
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论