多线程编程

进程Process VS线程Thread

 

进程包含线程,多任务既可由多进程实现,也可以由多线程实现。

多进程Process缺点:

1.创建进程Process比线程Thread开销大

2.进程间通信比线程间通信要慢,因为线程间通信就是读写同一个变量,速度快

多进程Process优点:

稳定性高,一个进程崩溃不会影响其他进程,但多线程会因为一个线程崩溃而崩溃

多线程Thread特点

1.多线程模型是Java程序最基本的并发模型

2.读写网络、数据库、Web开发都依赖Java多线程模型

 

线程Thread状态

Thread状态包含:New、Runnable、Blocked、Waiting、Timed Waiting和Terminated

public static void main(String[] args) throws InterruptedException {
    Thread t = new Thread(() -> {
        System.out.println("hello");
    });
    System.out.println("start");
    t.start();
    t.join();            // 等待线程运行结束
    System.out.println("end");
}

 

 如何中断线程

线程执行长时间任务,需要中断线程。中断线程的方式就是其他线程给需要中断的线程发送一个信号,该线程收到信号后结束执行run()方法。使用interrupt()方法来检测是否中断。

public class ThreadInterrupt {
    static class MyThread extends Thread {
        public void run() {
            int n = 0;
            while (!isInterrupted()) {    // 检测是否需要中断
                n++;
                System.out.println("run " + n + " time!");
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyThread();
        t.start();
        Thread.sleep(1);    // 当前线程暂停
        t.interrupt();      // 通知子线程中断
        t.join();
        System.out.println("main thread end");
    }
}
运行结果:
run 11 time!
run 12 time!
run 13 time!
run 14 time!
main thread end

标志位boolean running是一个线程间共享的变量。线程间共享变量需要使用volatile关键字标记,确保每个线程都能读取到更新后的变量值。

为什么要对线程间共享的变量用关键字volatile声明?这涉及到Java的内存模型。在Java虚拟机中,变量的值保存在主内存中,但是,当线程访问变量时,它会先获取一个副本,并保存在自己的工作内存中。如果线程修改了变量的值,虚拟机会在某个时刻把修改后的值回写到主内存,但是,这个时间是不确定的!

多线程编程_第1张图片

这会导致如果一个线程更新了某个变量,另一个线程读取的值可能还是更新前的。例如,主内存的变量a = true,线程1执行a = false时,它在此刻仅仅是把变量a的副本变成了false,主内存的变量a还是true,在JVM把修改后的a回写到主内存之前,其他线程读取到的a的值仍然是true,这就造成了多线程之间共享的变量不一致。

因此,volatile关键字的目的是告诉虚拟机:

  • 每次访问变量时,总是获取主内存的最新值;
  • 每次修改变量后,立刻回写到主内存。

volatile关键字解决的是可见性问题:当一个线程修改了某个共享变量的值,其他线程能够立刻看到修改后的值。

如果我们去掉volatile关键字,运行上述程序,发现效果和带volatile差不多,这是因为在x86的架构下,JVM回写主内存的速度非常快,但是,换成ARM的架构,就会有显著的延迟。

 

 

 

 

你可能感兴趣的:(Java)