java 多线程笔记
java 多线程笔记
nodaoli进程(Processor)和线程(Thread)的区别
进程是操作系统分配资源的最小单位,一个进程可以包含一个或多个线程。
线程是进程的子集,是进程中的子进程,是CPU调度的最小单位。
进程是资源分配的最小单位,线程是CPU调度的最小单位。
创建线程的三种方式
1 | public class SearchFile extends Thread{ |
1 | public class RunFile extends Thread{ |
1 | public class SearchFile implements Runnable{ |
1 | public class RunFile extends Thread{ |
1 | package multiplethread; |
start()和run()
直接调用run()方法,相当于调用了一个普通的Java方法,当前线程并没有任何改变,也不会启动新线程。上述代码实际上是在main()
方法内部又调用了run()
方法,打印hello语句是在main线程中执行的,没有任何新线程被创建。
必须调用Thread实例的start()
方法才能启动新线程,如果我们查看Thread类的源代码,会看到start()
方法内部调用了一个private native void start0()
方法,native修饰符表示这个方法是由JVM虚拟机内部的C代码实现的,不是由Java代码实现的。
线程的优先级
可以对线程设定优先级,设定优先级的方法是:
Thread.setPriority(int n) // 1~10, 默认值5
JVM自动把1(低)~10(高)的优先级映射到操作系统实际优先级上(不同操作系统有不同的优先级数量)。优先级高的线程被操作系统调度的优先级较高,操作系统对高优先级线程可能调度更频繁,但我们决不能通过设置优先级来确保高优先级的线程一定会先执行。
join()方法
当main线程对线程对象t调用join()
方法时,主线程将等待变量t表示的线程运行结束,即join就是指等待该线程结束,然后才继续往下执行自身线程。所以,上述代码打印顺序可以肯定是main线程先打印start,t线程再打印hello,main线程最后再打印end。
start–>hello–>end
1 | public class Main { |
守护线程(Daemon Thread)
守护线程是指为其他线程服务的线程。在JVM中,所有非守护线程
都执行完毕后,无论有没有守护线程,虚拟机都会自动退出。
因此,JVM退出时,不必关心守护线程是否已结束。
创建守护线程
在调用start()
方法前,调用setDaemon(true)
把该线程标记为守护线程:
1 | Thread t = new MyThread(); |
注意事项
守护线程的优先级永远是5,不能通过setPriority()
方法来改变。
守护线程不能启动新线程,否则会抛出IllegalThreadStateException
异常。
守护线程不能访问非守护线程的成员变量,因为当守护线程结束后,JVM退出,非守护线程的成员变量也就不存在了。
守护线程不能抛出UncaughtException
异常,因为JVM退出时,会先销毁守护线程,如果守护线程抛出异常,将导致JVM退出。
守护线程不能调用interrupt()
方法,因为JVM退出时,会先销毁守护线程,如果守护线程调用interrupt()
方法,将导致JVM退出。
守护线程不能调用join()
方法,因为JVM退出时,会先销毁守护线程,如果守护线程调用join()
方法,将导致JVM退出。
守护线程不能调用setUncaughtExceptionHandler()
方法,因为JVM退出时,会先销毁守护线程,如果守护线程调用setUncaughtExceptionHandler()
方法,将导致JVM退出。
守护线程不能调用setName()
方法,因为JVM退出时,会先销毁守护线程,如果守护线程调用setName()
方法,将导致JVM退出。
守护线程不能调用setPriority()
方法,因为JVM退出时,会先销毁守护线程,如果守护线程调用setPriority()
方法,将导致JVM退出。
守护线程不能调用setDaemon()
方法,因为JVM退出时,会先销毁守护线程,如果守护线程调用setDaemon()
方法,将导致JVM退出。
守护线程不能调用setContextClassLoader()
方法,因为JVM退出时,会先销毁守护线程,如果守护线程调用setContextClassLoader()
方法,将导致JVM退出。
为什么使用synchronized需要创建一个Object对象作为锁?
synchronized
修饰的方法或代码块,必须指定一个锁对象,这个锁对象可以是任意对象,只要确保这个对象是唯一的。
我的理解是:这是一个yellow 遥控器,被访问的对象就是green 电视机,只有拿到yellow 遥控器才能控制green 电视机,所以遥控器就是锁对象
。