一、什么是线程
一个进程可包含多个线程;进程是重量级的,开关比较消耗资源;windows中可指定进程的线程分配到哪个CPU上执行;
二、线程的基本操作
1、几种状态:new - runnable(供物理CPU调度执行)- terminated - blocked - waiting - timed waiting
2、创建线程两种方式:继承Thread类;实现Runnable接口
3、Thread t1 = new Thread().start() 开启线程;直接调用run不能开启新的线程,是在调用run()的线程中执行的;
4、线程的终止:Thread.stop()不推荐使用,线程异常终止,引起未知的异常,如多线程数据不一致等;
5、线程的中断:void Thread.interrupt();(中断线程),boolean Thread.isInterrupt();(判断是否中断),static boolean Thread.interrupt()(判断是否中断,并清除当前中断状态)
public void run(){
while(true){
if(Thread.currentThread().isInterrupted()){ (若调用interrupt()中断while循环线程,需要这样写)
System.out.println("Interruted!");
break;
}
Thread.yield();
}
}
6、static void sleep(long mills) throws InterruptedException; 有中断异常需要捕获
public void run(){
while(true){
if(Thread.currentThread().isInterrupted()){
System.out.println("Interruted!");
break;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("Interruted When Sleep");
//设置中断状态,抛出异常后会清除中断标记位
Thread.currentThread().interrupt();
}
Thread.yield();
}
}
7、挂起(suspend())和继续操作(resume())线程:不推荐使用
8、suspend()不会释放锁;如果加锁放生在resume()之后,则产生死锁(即线程先调用了resume()再调用suspend(),导致线程一直被挂起)
9、yield():释放掉当前线程自己所占用的CPU,重新竞争CPU资源;
10、join():使线程执行完成,等待调用线程结束;底层使用wait()方法实现,线程执行结束后使用notifyAll()唤醒所有线程;
三、守护线程
在后台默默完成一些系统性的服务,比如垃圾回收,JIT线程就可理解为守护线程;
当一个java应用内只有守护线程时,java虚拟机就自然退出;
thread.setDaemon(true);(在start()方法之前设置)
四、线程优先级
MAX_PRIOPIRY=10; MIN_PRIOPIRY=1; NORMAL_PRIOPIRY=5;
五、基本的线程同步操作
1、synchronized
指定加锁对象:对给定的对象加锁,进入同步代码前必须获得给定对象的锁;(java内置,在虚拟机内部实现,比如线程挂起前做些优化、自旋等待等)
直接作用于实例方法;相当于对当前实例加锁,进入同步代码块前必须获得当前实例的锁;
直接作用于静态方法:相当于对当前类加锁,进入同步块前获得类的锁
2、Object.wait()、 Object.notify()
线程调用wait()进入等待状态,释放对象monitor的所有权,前提是必须获得对象的锁(synchronized代码块中);
notify()执行前也要先获得对象锁,随机唤醒其中一个等待的线程(wait());
wait()线程要等待notify()线程释放锁之后,才能获得锁,才能继续执行;
notifyAll()唤醒全部的等待线程,线程竞争CPU资源;