并发编程 - Java线程的一大堆

一、通用的线程生命周期

在这里插入图片描述
1、初始状态:线程被创建,但是还允许被分配cpu执行。
2、可运行状态:线程可以分配cpu执行。
3、运行状态:线程正在被cpu执行。
4、休眠状态:运行的时候,如果被阻塞或者等待某个事件,就会从运行状态转为休眠状态,同时释放cpu资源,如果等到了事件,则会转为可运行状态;
5、结束状态:线程运行完成或者出现异常。

二、Java的线程生命周期

在这里插入图片描述
线程的六个状态如上图所示(呱唧呱唧,好看)
new:创建一个线程,为线程分配内存并初始化其成员变量的值;
runnable:start方法之后将转为就绪状态,此时jvm完成了方法调用栈和程序计数器的创建,等待该线程的调度和运行;
running:争取到cpu资源,开始执行run方法;
blocked:同步阻塞,未获取到同步锁;
waiting/timed_waiting:等待阻塞

2.1 创建线程的方式

(1)、继承thread方法,重写run方法
package exercise_03_0712_thread;

public class ThreadTest1 extends Thread {
    @Override
    public void run() {
        System.out.println("thread is run~");
    }

    public static void main(String[] args) {
        ThreadTest1 threadTest1 = new ThreadTest1();
        threadTest1.start();
    }
}
(2)、实现runnable接口,重写run方法
package exercise_03_0712_thread;

public class ThreadTest2 implements Runnable {
    @Override
    public void run() {
        System.out.println("thread is run~");
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new ThreadTest2());
        thread.start();
    }
}

(3)通过ExcutorService和Callable 实现有返回值的线程
package exercise_03_0712_thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ThreadTest3 implements Callable<String> {
    private String name;
    public ThreadTest3(String name) {
        this.name = name;
    }
    @Override
    public String call() throws Exception {
        System.out.println(Thread.currentThread().getName()  + " call");
        return name;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        List<Future> list = new ArrayList<>();
        for (int i = 0; i < 2; ++i) {
            Callable callable = new ThreadTest3(i + "");
            // 提交线程
            Future future = threadPool.submit(callable);
            System.out.println("submit thread : " + i);
            list.add(future);
        }
        // 关闭线程池
        threadPool.shutdown();
        // 遍历所有线程的结果
        for (Future future : list) {
            System.out.println("get future result: " + future.get().toString());
        }
    }
}

(4)基于线程池
package exercise_03_0712_thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadTest4 {

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 2; ++i) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " is run");
                }
            });
        }
        threadPool.shutdown();
    }
}

2.2 线程的启动

start和run方法的区别?
源码:
在这里插入图片描述
run方法:在独立执行的线程中被调用。
在这里插入图片描述
start方法在jvm会做两个比较重要的事情:
(1)、new一个java 线程,os::create_Thread();
(2)、调用Thread::start去启动刚才构造的线程,并把它的状态置为RUNNABLE;
所以,线程的start是基于操作系统去构造一个线程的启动,回调run方法,把它的状态置为RUNNABLE。
代码验证:
start:
在这里插入图片描述
run:
在这里插入图片描述
(1)、start方法启动一个线程时,线程处于就绪状态,并没有运行。而调用run方法,线程就会进入运行状态,开始运行run方法里的代码,在run方法运行结束后,cpu再调度其他线程。
(2)、在调用了start之后,线程会在后台执行,无需等待run方法执行完毕。

2.3 线程的终止

(1)、正常运行结束

即run方法执行完毕

(2)、使用退出标志终止线程

用一个变量来控制循环,变量用volatitle修饰,可保证线程安全。

    private volatile static boolean flag = true;
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " thread is run~");
        while (flag) {
            System.out.println("running");
        }
        System.out.println(Thread.currentThread().getName() + " thread is over~");
    }
(3)、使用interrupt方法终止线程

a、线程处于阻塞状态时,调用interupt,会抛出异常

package exercise_03_0712_thread;

public class InterruptedTest extends Thread{
    @Override
    public void run() {
        while (!isInterrupted()) {
            System.out.println("run");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        InterruptedTest interruptedTest = new InterruptedTest();
        interruptedTest.start();
        Thread.sleep(1000);
        interruptedTest.interrupt();
    }
}

捕捉这个异常,然后进行退出。
在这里插入图片描述
b、线程不处于阻塞状态,调用interrupt,线程中可以使用isinterrupted来判断是否终止线程。
线程默认的interrupted值为false;
调用了interrupt(),interrupted就会变成true;

package exercise_03_0712_thread;

public class InterruptedTest extends Thread{
    @Override
    public void run() {
        while (!isInterrupted()) {
            System.out.println("run");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        InterruptedTest interruptedTest = new InterruptedTest();
        interruptedTest.start();
        Thread.sleep(1000);
        interruptedTest.interrupt();
    }
}
(2)、使用stop,不建议使用,已过期

stop杀死线程,如果线程含有synchronized锁,也不会释放。

2.3 线程的复位

第一种:Thread.interrupted()

package exercise_03_0712_thread;

public class InterruptedTest extends Thread{
    @Override
    public void run() {
        while (true) {
            if (isInterrupted()) {
                System.out.println("before: " + Thread.currentThread().isInterrupted());
                Thread.interrupted();//复位,回到原始状态
                System.out.println("after: " + Thread.currentThread().isInterrupted());
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        InterruptedTest interruptedTest = new InterruptedTest();
        interruptedTest.start();
        Thread.sleep(1000);
        interruptedTest.interrupt();
    }
}

在这里插入图片描述
第二种:异常
正在阻塞中的线程被中断,会抛异常的,也会让线程的interrupted标记复位。

package exercise_03_0712_thread;

public class InterruptedTest extends Thread{
    @Override
    public void run() {
        while (!isInterrupted()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("isInterrupted: " + isInterrupted());
                break;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        InterruptedTest interruptedTest = new InterruptedTest();
        interruptedTest.start();
        Thread.sleep(1000);
        interruptedTest.interrupt();
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值