一、线程(Thread)
1、线程的创建
Java创建线程是采用内核线程: 由操作系统内核支持的线程,通过操纵调度器对线程进行调度(内核切换线程),将线程的任务映射到各个处理器上。
调native方法 —> 调C++ -> 调操作系统(通过操作系统的库函数创建的线程)。
优点:
一个线程阻塞,不影响另一个线程的执行;
缺点:
1、由于是基于内核线程实现的,所以各种线程操作,如创建、休眠及同步,都需要进行系统调用,而系统调用的代价相对较高;
2、操作系统内核支持的线程数量是有限的,不能无限制地创建线程;
1.通过Thread类,重写run()方法
/*** 1.创建Thread*/
Thread thread01 = new Thread(){@Overridepublic void run(){Thread.currentThread().setName("new Thread的线程");System.out.println(""+Thread.currentThread().getName());}
};class ThreadDemo extends Thread{@Overridepublic void run() {Thread.currentThread().setName("继承Thread的线程");System.out.println(""+Thread.currentThread().getName());}
}/*** 2.继承Thread类*/
ThreadDemo thread02 = new ThreadDemo1();
thread02.start();
2.通过Runnable接口,重写run()方法。
public class DisplayTime implements Runnable {@Overridepublic void run() {while (true) {System.out.println(Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
3.通过Callable接口,实现Callable和Future,重写Call()方法。
public class DisplayTime implements Callable<String> {@Overridepublic String call() throws Exception {System.out.println(Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "返回值";}public static void main(String[] args) {DisplayTime displayTime = new DisplayTime();FutureTask<String> stringFutureTask = new FutureTask<>(displayTime);new Thread(stringFutureTask, "线程一").start();try {System.out.println("线程的返回值:" + stringFutureTask.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}
}
2、线程的属性
线程是一个可调操作系统的对象,他的start()、stop()、yield()、sleep(long var0)...等线程方法都是调用操作系统执行。
public class Thread implements Runnable {private long tid; 线程的ID, 由线程自己分配private volatile String name; 线程的名称, 可以手动设置(setName())private int priority; 线程的优先级, 默认5, 最小1, 最大10private ThreadGroup group; 线程所属的线程组private ClassLoader contextClassLoader; 次线程上下文ClassLoaderprivate boolean daemon = false; 是否是守护线程private volatile int threadStatus = 0; 线程的状态. 对应静态枚举类Stetepublic void run(){} 线程的功能方法public synchronized void start(){} 线程准备就绪,等待程序调用run()方法. 异步操作, 调用顺序不代表实际启动的顺序.public final void stop(){} 终止当前线程, 不建议使用public static native void sleep(long var0){} 指定毫秒数让正在执行的线程暂停, 具体取决于系统定时器和调度程序的精度和准确性public final void setPriority(int var1){} 设置优先级, 不一定有用, 影响线程执行优先级的因素很多public final void setDaemon(boolean var1){} 设置守护线程标识public static native void yield(){} 放弃当前CPU执行资源,放弃时间不确定public final native boolean isAlive(){} 判断线程是否处于活动状态. 活动状态: 启动未终止public final void resume(){} 恢复线程, 不建议使用public final void suspend(){} 暂停线程, 不建议使用public void interrupt(){} 中断线程public static boolean interrupted(){} 测试当前线程是否中断, 并且具备清除状态的功能public boolean isInterrupted(){} 测试当前线程是否中断public final void join(){} 等待调用的这个线程终止public Thread.State getState(){} 获取线程状态
}
3、线程的状态
1.新建(New):创建后未启动(未调用start()方法)的线程处于这种状态。
2.就绪(Ready):调用start()方法,进入就绪状态。等待CPU调度执行。
3.运行(Running):该状态可能正在CPU执行,也可能在等待CPU执行。
注意: 线程要想进入运行状态执行,首先必须处于就绪状态中。
4.无限期等待(Waiting):不会分配CPU执行时间,要等待被其他线程显式唤醒。Object.wait()方法可让其无限等待
5.限期等待(Timed Waiting): 不会分配CPU执行时间,在一定时间之后它们会由系统自动唤醒。Object.wait(long millis)方法让线程进入限期等待状态。
6.阻塞(Blocked):线程在获取排他锁失败(因为锁被其它线程所占用),进入同步阻塞状态。
7.死亡(Dead):线程执行完了或者因异常退出了run()方法,该线程生命周期结束。
4、线程的一些方法
1.Thread.sleep(long millis):当前线程调用此方法,进入阻塞,不释放对象锁,线程自动唤醒进入可运行状态。
2.Thread.yield():当前线程调用此方法,放弃获取的cpu时间片,由运行状态变可运行状态,让OS再次选择线程。实际中无法保证yield()达到让步目的,Thread.yield()不会导致阻塞。
3.Thread.join()/thread.join(long millis):当前线程里调用其它线程的join方法,当前线程阻塞,但不释放对象锁,待别的线程执行结束,当前线程进入可运行状态。
4.Obj.wait():当前线程调用释放对象锁(需先拿锁),进入等待队列。
5.Obj.notify():唤醒在此对象监视器上等待的单个线程,选择是任意性的。
6.Obj.notifyAll():唤醒在此对象监视器上等待的所有线程。