并发编程基础

创建线程的方式

创建线程一般通过继承Thread、实现Runnable接口、ExecutorService、Callable和Future等多种方式。

Thread实现

package all;
public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("测试Thread");
    }
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        myThread1.start();
        MyThread myThread2 = new MyThread();
        myThread2.start();
    }
}

Runnable实现

package all;
public class MyRunnable implements Runnable {
    private volatile int i =5;
    @Override
    public void run() {
        while (i > 0){
            System.out.println("Runnable测试");
            --i;
        }
    }
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
        Thread thread1 = new Thread(myRunnable);
        thread1.start();
    }
}

Callable和FutureTask

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable<String> {

    public String call() throws Exception {
        return "TestCallable";
    }
    public static void main(String[] args) throws Exception {
        FutureTask<String> futureTask = new FutureTask(new MyCallable());
        futureTask.run();
        if(futureTask.isDone()){
            System.out.println(futureTask.get());
        }
    }
}

线程的生命周期

1.NEW:初始状态,线程被创建,但是还没有调用start方法
2.RUNNABLE:运行状态,JAVA 线程把操作系统中的就绪和运行两种状态统一称为“运行中”
3.BOLCKED:阻塞状态,表示线程进入等待状态,也就是线程因为某种原因放弃了 CPU 使用权,阻塞也分为几种情况
–>等待阻塞:运行的线程执行 wait 方法,jvm 会把当前线程放入到等待队列
–>同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其他线程锁占用了,那么jvm会把当前的线程放入到锁池中
–>其他阻塞:运行的线程执行 Thread.sleep 或者 t.join 方法,或者发出了I/O请求时,JVM 会把当前线程设置为阻塞状态,当 sleep 结束、join线程终止、io处理完毕则线程恢复
4.TIME_WAITING:超时等待状态,超时以后自动返回
5.TERMINATED:终止状态,表示当前线程执行完毕
在这里插入图片描述

代码演示:

import java.util.concurrent.TimeUnit;
public class ThreadTest {
    public static void main(String[] args) {
        //TIME_WAITING
        new Thread(()->{
            while (true){
                try {
                    TimeUnit.SECONDS.sleep(1000);
                }catch (InterruptedException ex){
                    ex.fillInStackTrace();
                }
            }
        },"测试Time_Waiting").start();

        //WAITING
        new Thread(()->{
            while (true){
               synchronized (ThreadTest.class){
                   try {
                       ThreadTest.class.wait();
                   }catch (InterruptedException ex){
                       ex.fillInStackTrace();
                   }
               }
            }
        },"测试WAITING").start();

        new Thread(new BlockedDemo(),"BlockedDemo01").start();
        new Thread(new BlockedDemo(),"BlockedDemo02").start();
    }
}
class BlockedDemo extends Thread{

    public void run(){
        synchronized (BlockedDemo.class){
            while(true){
                try {
                    TimeUnit. SECONDS .sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

通过idea终端输入jps查到线程进程,使用jstack 进程查看堆栈信息

终止线程(Interrupt)

其它线程通过调用当前线程的Thread.Interrupt()方法向当前线程发送一个信号,告诉它可以中断线程的执行了,至于什么时候中断,取决于当前线程自己。
判断线程是否中断可以使用Thread.currentThread().isInterrupted()来实现。

下面是一个例子:

package all;
public class ThreadTest {
    private static int i;
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(()->{
            //默认状态是false,
            while(!Thread.currentThread().isInterrupted()){
                i++;
            }
            System.out.println("Num:"+i+",isInterrupted:"+Thread.currentThread().isInterrupted());
        },"测试线程");
        thread.start();
        Thread.sleep(1);
        //发送中断标识,isInterrupted赋值true
        thread.interrupt();  //可以注释掉试试效果
    }
}

执行结果:

Num:7124,isInterrupted:true
Process finished with exit code 0

线程的复位

线程的中断就是通过Thread.Interrupt()方法把isTerrupted的值从false改为true,但是中断把值改为true以后什么也没有做,是不是应该恢复到原始值呢,恢复原始值就是线程的复位通过Thread.interrupted,这只是我的个人理解。

通过同一个代码对比一下:

package all;
public class ThreadTest {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(()->{
            while(true){
                //初始值是flase
               if(Thread.currentThread().isInterrupted()){
                   System.out.println("复位前的值:"+Thread.currentThread().isInterrupted());
                   Thread.interrupted();
                   System.out.println("复位后的值:"+Thread.currentThread().isInterrupted());
               }
            }
        },"测试线程Thread.interrupted()");
        thread.start();
        Thread.sleep(1);
        thread.interrupt(); //发送中断标识赋值为true
    }
}

执行结果:

复位前的值:true
复位后的值:false

为什么要复位

Thread.interrupted()是属于当前线程的,是当前线程对外界中断信号的一个响应,表示自己已经得到了中断信号,
但不会立刻中断自己,具体什么时候中断由自己决定,让外界知道在自身中断前,他的中断状态仍然是 false,这就
是复位的原因。

线程的启动原理

在这里插入图片描述
从图中可以看出start方法会通过JVM创建一个线程,然后回调run方法,等于是主线程和新创建的线程一起执行。
run方法没有创建怎么线程只有一个主线程等于同步执行。

总结图

在这里插入图片描述


版权声明:本文为qq_16438883原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。