Java并发-线程基础

更多互联网新鲜资讯、工作奇淫技巧关注原创【飞鱼在浪屿】(日更新)
Java并发-线程基础文章插图
JavaThread对象允许我们在单独的线程中运行代码 。 当应用程序启动时 , JVM将创建名为的初始线程main 。 main方法在主线程上运行 。 在应用程序内部 , 我们可以创建新线程以与主线程并行执行其他任务 。
Java使用本机操作系统线程 。 因此 , 一个操作系统线程映射了一个Java线程 。
创建线程Thread类的构造函数带有一个Runnable对象 。 可运行接口具有一个抽象run方法 , 该方法称为Thread#start()方法 。 它可以由lambda , 匿名类或实现Runnable方法的类实例化 。
Java并发-线程基础文章插图
通常 , 使用lambda更容易且更紧凑:
Thread thread = new Thread(() -> {// content of run command});thread.start();只要线程的运行挂钩方法没有返回 , 线程就一直存在 。 调度程序可以挂起并运行线程多次 。 为了使线程永远执行 , 它需要一个无限循环来防止其返回 。
Join方法允许一个线程等待另一个线程的完成 。 这是屏障同步的一种简单形式 。
Java并发-线程基础文章插图
Java线程类型:用户和守护程序线程JVM启动时 , 它包含一个名为主线程的用户线程 。 用户线程和守护程序线程之间的主要区别是它们退出时会发生什么 。

  • 即使主线程退出 , 用户线程也会继续其生命周期 。
  • 但是 , 当所有用户线程退出时 , 所有守护进程线程都会终止 。
  • 当所有用户线程退出时 , JVM本身退出 。
线程类包含布尔daemon字段 , 用于指定线程是否为守护程序 。 可以在创建时通过构造函数或setter方法进行设置 。
Thread thread = new Thread(getRunnable());thread.setDaemon(true);thread.start();默认情况下 , 守护程序字段为false , 因此我们生成的大多数线程都是用户线程 。 isDaemon如果未指定 , 则线程会复制父线程的状态 。 Java使用守护线程在一些场景 , 如ForkJoinPool和Timer 。 为了说明 , 看以下示例:
public class Main {public static void main(String[] args) throws InterruptedException, ExecutionException {//runDeamonThread();runUserThread();System.out.println(getCurrentThreadName() + " exits");}private static void runDeamonThread() throws ExecutionException, InterruptedException {ExecutorService executorService = Executors.newWorkStealingPool(10);executorService.execute(getRunnable());}private static void runUserThread() {Thread thread = new Thread(getRunnable());thread.start();}private static Runnable getRunnable() {return () -> {for (int i = 0; i <= 200; i++) {System.out.print(".");Thread.yield();}System.out.println(getCurrentThreadName() + " exits. isDeamon: " + isDaemon());};}private static boolean isDaemon() {return Thread.currentThread().isDaemon();}private static String getCurrentThreadName() {return Thread.currentThread().getName();}}
  • 当调用runUserThread方法时 , 它显示以下示例输出:
................................................main exits........................................................................................Thread-0 exits. isDeamon: false
  • 第二种情况是调用runDeamonThread , 以ForkJoinPoolDaemon Threads为例 。 可以简单地使用setDaemon(true)方法 。 输出:
main exits因此 , 当main方法退出时 , 所有用户线程都将终止 , JVM退出并杀死所有守护程序线程 , 因此我们甚至没有机会看到守护程序线程的输出 。
停止线程与创建相比 , 停止线程是一件非常困难的事情 。 一旦线程开始运行 , 它就会与调用者分离开来 , 并且它具有自己的生命周期 。 它可以完成任务并退出 , 或者如果它长时间运行 , 则可以永远工作 。 Java没有为我们提供自愿停止线程的方法(不建议使用) 。
  1. 简单的方法可能是使用停止标志:
volatile boolean isStopped = false;public void test() {new Thread(() -> {while (!isStopped) {System.out.print(".");}System.out.println("Child Exits");}).start();try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}isStopped = true;System.out.println("Main exits");}该标志用volatile为了使两个线程都可以看到其最新值 。 但是 , 如果线程被阻塞sleep , wait , join或阻塞I / O操作 , 那么将失败 。
2.停止的另一种方法是使用线的interrupt()方法 。
对线程的中断请求表明它应该停止正在执行的操作并执行其他操作 。 程序员可以准确地决定线程如何响应中断 。