线程的实现方式
1.使用Thread类或继承Thread类
Thread thread = new Thread() {@Overridepublic void run() {//do something}};thread.start();
2.实现Runnable接口
Runnable runnable = new Runnable() {@Overridepublic void run() {//do somethingSystem.out.println("do something");}};Thread thread = new Thread(runnable);thread.start();
3.使用有返回值的Callable
public class CallableTest implements Callable<Integer> {@Overridepublic Integer call() throws Exception {return new Random().nextInt();}}ExecutorService service = Executors.newFixedThreadPool(10);Future<Integer> future = service.submit(new CallableTest());System.out.println(future.get());
4.使用lambda
new Thread(() -> {System.out.println(Thread.currentThread().getName());}).start();
Java线程执行为什么不能直接调用run()方法,而要调用start()方法?
Java 中实现真正的多线程是 start 中的 start0() 方法,start0是native方法�,直接执行run() 方法只是当普通的方法调用。
CAS涉及到用户模式到内核模式的切换吗?
不涉及,因为CAS只是一个指令。
JAVA的线程都是内核线程。
Java线程调度是抢占式调度
抢占式线程调度:每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定,线程执行时间系统可控,也不会有一个线程导致整个进程阻塞。
Java语言一共10个级别的线程优先级(1-10,默认是5),在两线程同时处于ready状态时,优先级越高的线程越容易被系统选择执行。但优先级并不是很靠谱,因为Java线程是通过映射到系统的原生线程上来实现的,所以线程调度最终还是取决于操作系统。
Java线程的生命周期
Java语言中线程共有六种状态,分别是:
- NEW(初始化状态)
- RUNNABLE(可运行状态+运行状态)
- BLOCKED(阻塞状态)
- WAITING(无时限等待)
- TIMED_WAITING(有时限等待)
- TERMINATED(终止状态)
Thread常用方法
- sleep方法,调用sleep会让当前线程从Running进入TIMED_WAITING状态,不会释放对象锁.
- yield方法,yield会释放CPU资源,让当前线程从Running进入Runnable状态,让优先级更高(至少是相同)的线程获得执行机会,不会释放对象锁;
join方法,调用join方法后,会等待join的方法结束再执行其他线程,一般用于等待异步线程执行完结果之后才能继续运行的场景。 ```java Thread t = new Thread(new Runnable() {
@Overridepublic void run() {System.out.println("thread begin...");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("thread end...");}});t.start();//主线程会等待线程t执行完t.join();System.out.println("main end...");
===================== thread begin… thread end…
main end…
<br /><a name="bOcTK"></a>## Java线程的中断机制Java没有直接的方法来停止某个线程,而是提供了中断机制。中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理。被中断的线程拥有完全的自主权,它既可以选择立即停止,也可以选择一段时间后停止,也可以选择不停止。<a name="AUG8I"></a>### API的使用:- interrupt():将线程的中断标志位设置为true,不会停止线程。- isInterrupted():判断当前线程的中断标志位是否为true,不会清除中断标志位- Thread.interrupted():判断当前线程的中断标志位是否为true,并清除中断标志位,重置为fasle```javaSystem.out.println("begin...");Thread t = new Thread(new Runnable() {@Overridepublic void run() {while (true) {i++;System.out.println(i);//Thread.interrupted(); 清除中断标志位,不会打印下面的===========//Thread.currentThread().isInterrupted(); 不会清除中断标志位,继续打印下面的===========if (Thread.currentThread().isInterrupted()) {System.out.println("===========");}if (i == 10) {break;}}}});t.start();//不会停止线程,只是设置了一个中断标志位为truet.interrupt();
利用中断机制停止线程
public class StopThread implements Runnable {@Overridepublic void run() {int count = 0;while (!Thread.currentThread().isInterrupted() && count < 100) {System.out.println("count:" + count);count++;}System.out.println("线程stop...");}public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new StopThread());t.start();Thread.sleep(5);Thread.interrupted();}}

处于休眠中的线程被中断,线程是可以感受到中断信号的,并且会抛出一个InterruptedException异常,同时清除中断信号,将中断标记位设置成false。
sleep可以被中断抛出中断异常:sleep interrupted,清除中断标志位
wait可以被中断抛出中断异常:InterruptedException,清除中断标志位
Java线程间通信
volatile
volatile有两大特性,一是可见性,二是有序性,禁止指令重排序,其中可见性就是可以让线程之间进行通信。
等待唤醒机制
等待唤醒机制可以基于wait和notify方法来实现,在一个线程内调用该线程锁对象的wait方法,线程将进入等待队列进行等待直到被唤醒。
LockSupport
LockSupport是JDK中用来实现线程阻塞和唤醒的工具,线程调用park则等待“许可”,调用unpark则为指定线程提供“许可”。使用它可以在任何场合使线程阻塞,可以指定任何线程进行唤醒,并且不用担心阻塞和唤醒操作的顺序,但要注意连续多次唤醒的效果和一次唤醒是一样的。
