1.什么是线程
将线程理解为轻量级进程,它与进程的最大的区别是:
多个线程共享一个进程资源;
对于OS的许多资源的分配和管理(如内存)通常都是进程级别的,线程只是os调度的最小单位;
相对于进程来说更轻量,上下文信息更少,创建、销毁更简单,若线程被挂起,不会导致整个进程被挂起。
2.在java中如何使用线程
- 实现Runnable接口,然后通过new Thread(new RunnableImpl()).start();创建线程。
public interface Runnable { public abstract void run(); }
- 继承Thread类(Thread类自身实现了Runnable接口), new MyThread().start()创建线程。
start()方法是怎么启动线程的? - 摘自《java特种兵》
实现方式1
基于Kernel Thread(KLT)的映射来实现:KLT是内核线程,内核线程由OS直接完成调度切换,它相对应用程序的线程来讲只是一个借口,
外部程序会使用一种轻量级进程(Light Weight Process, LWP)来与KLT进行一对一的借口调用。
也就是说,进程内部会尝试利用OS的内核线程去参与实际的调度,而自己使用API调用作为中间桥梁与自己的程序交互。
3.JAVA中线程的状态
- NEW (执行 start()之前,需注意:调用了start()并不代表状态立即改变,中间还有一些步骤,要看那些中间步骤是否已经完成了)
- RUNNABLE (可以理解为活着并尝试征用CPU)
- BLOCKED(阻塞状态,或者说线程已被挂起, 是在多个线程有同步操作的场景, 比如正在等待另一个线程的synchronized 块的执行释放, 或者可重入的 synchronized块里别人调用wait() 方法, 也就说线程在等待进入临界区)
- WAITING (一个线程拥有锁对象后,执行wait()方法)
- TIMED_WAITING (sleep()之后进入此状态)
- TERMINATED (run()方法执行结束后就处于此状态,在操作系统内部可能已经注销了相应的线程,活着将它复用给其他需要使用线程的请求)
4.线程优先级
cpu的资源是有限的,在某些情况下,我们可以设置线程的优先级,让OS根据不同的优先级进行调度
线程调度的优先级,每个OS都有不同的实现,java虚拟机为了兼容各种OS设定了1-10个优先级,理论上数字越大,优先级越高。
而某些OS可能只有3-5个线程,那么jvm会根据实际情况将 1-10这10个数字与OS的线程优先级做一个映射关系。
那么思考一下,很有可能 优先级3 和 优先级5 在OS中是同一个优先级。
java中通过setPriority(int)方法来设置一个线程的优先级。 在实际工作中,通常将优先级设置为普通(5,默认),最大(10),最小(1)。
5.守护线程
java中有两类线程 User Thread 和 Daemon Thread
守护线程--也称“服务线程”,在没有用户线程可服务时会自动离开。(GC 即为一个守护线程)
java中通过setDaemon(true) 将一个线程设置为守护线程,但是需注意两点
1.thread.setDaemon(true)必须在thread.start()之前设置,否则将会抛出IllegalThreadStateException异常
2.在Daemon线程中产生的新线程也是Daemon的
Thread中setDaemon实现
public final void setDaemon(boolean on) { checkAccess(); if (isAlive()) { throw new IllegalThreadStateException(); } daemon = on; }