一、线程命名和取得
线程的所有操作方法几乎都在Thread类中定义好了
从本质上上来讲,多线程的运行状态并不是固定的,唯一的区别就在于线程的名称上。
起名:尽可能避免重名,或者避免修改名称。
在thread类中提供如下方法:
构造方法:public Thread(Runnable target, String name)
设置名字:public final synchronized void setName(String name)
取得名字:public final String getName()
既然线程本身是不缺定的状态,所以如果要取得线程名字的话,那么唯一能做的就是取得当前线程的名字。
所以在Thread类中有提供如下方法:
public static native Thread currentThread();
示例1:

class MyThread6 implements Runnable { @Override public void run() {// 主方法 for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + ",i:" + i); } } }
main方法
MyThread6 myThread6 = new MyThread6(); new Thread(myThread6, "线程A").start(); new Thread(myThread6).start(); new Thread(myThread6).start();
如果在设置线程对象时没有设置具体名字,那么就采用一个默认的名字进行定义。
示例2
class MyThread7 implements Runnable { @Override public void run() {// 主方法 System.out.println("MyThread7线程类:" + Thread.currentThread().getName()); } }
main方法
MyThread7 myThread7 = new MyThread7(); new Thread(myThread7, "线程A").start(); myThread7.run();
输出
MyThread7线程类:线程A【new Thread(myThread7, "线程A").start();】
MyThread7线程类:main【myThread7.run();】
结论
线程依附于进程,那么进程在哪里?
每当使用java命令在JVM上解释一个程序执行的时候,那么都会默认的启动一个JVM的进程,而主方法只是这进程中的一个线程,所以整个程序一直都泡在线程的运行机制上
每一个JVM至少会启动两个线程,主线程、GC线程
二、休眠
如果想让某些线程延缓执行,那么就可以使用休眠的方式来进行处理,在Thread类里面提供如下休眠操作 。
休眠方法:public static native void sleep(long millis) throws InterruptedException;
InterruptedException:如果休眠时间没到就停止休眠了,那么就会产生中断异常
示例代码1:

class MyThread8 implements Runnable { @Override public void run() {// 主方法 for (int i = 0; i < 100; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ",i=" + i); } } }
main方法
MyThread8 mt = new MyThread8(); new Thread(mt, "线程A").start(); new Thread(mt, "线程B").start(); new Thread(mt, "线程C").start();
输出
线程C,i=0
线程A,i=0
线程B,i=0
线程A,i=1
线程B,i=1
线程C,i=1
结论:以上代码执行中感觉像是所有的线程对象都同时休眠了,但严格来讲不是同时,是有先后顺序的,只不过顺序小一点而已。
示例2
main方法
MyThread8 mt = new MyThread8(); Thread thread = new Thread(mt, "线程A"); thread.start(); Thread.sleep(3000); thread.interrupt();
结论:要想中断必须在其他线程操作。
三、优先级
从理论上来讲优先级越高的线程越有可能先执行。而在Thread类里面定义有以下的优先级操作方法。
设置优先级:public final void setPriority(int newPriority)
对于优先级一共定义三种:
最低优先级:public final static int MIN_PRIORITY = 1;
中等优先级:public final static int NORM_PRIORITY = 5;
最高优先级:public final static int MAX_PRIORITY = 10;
取得优先级:public final int getPriority()
示例1,观察优先级

class MyThread8 implements Runnable { @Override public void run() {// 主方法 for (int i = 0; i < 100; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ",i=" + i); } } }
main 方法

MyThread8 mt = new MyThread8(); Thread threadA = new Thread(mt, "线程A"); Thread threadB = new Thread(mt, "线程B"); Thread threadC = new Thread(mt, "线程C"); threadA.setPriority(Thread.MAX_PRIORITY); threadB.setPriority(Thread.MIN_PRIORITY); threadC.setPriority(Thread.MIN_PRIORITY); threadA.start(); threadB.start(); threadC.start();
理论上A最先
示例2、查看当前线程优先级
System.out.println(Thread.currentThread().getPriority());
结论:
1.线程要有名称,Thread.currentThread()取得当前线程;
2.线程休眠是有先后顺序的;
3.理论上线程的优先级越高,越先执行
四、深入理解线程状态
利用JDK提供的jstack工具,查看下thread dump文件中线程的状态。NEW、RUNNABLE、TERMINATED这3个状态很容易理解,主要说明其它3种状态。
1、显示BLOCKED状态

public class BlockedState { private static Object object = new Object(); public static void main(String[] args) { Runnable task = new Runnable() { @Override public void run() { synchronized (object) { long begin = System.currentTimeMillis(); long end = System.currentTimeMillis(); // 让线程运行5分钟,会一直持有object的监视器 while ((end - begin) <= 5 * 60 * 1000) { } } } }; new Thread(task, "t1").start(); new Thread(task, "t2").start(); } }
先获取object的线程会执行5分钟,这5分钟内会一直持有object的监视器,另一个线程无法执行处在BLOCKED状态
通过thread dump可以看到:t2线程确实处在BLOCKED (on object monitor)。waiting for monitor entry 等待进入synchronized保护的区域。
2、显示WAITING状态

public class WaitingState { private static Object object = new Object(); public static void main(String[] args) { Runnable task = new Runnable() { @Override public void run() { synchronized (object) { long begin = System.currentTimeMillis(); long end = System.currentTimeMillis(); // 让线程运行5分钟,会一直持有object的监视器 while ((end - begin) <= 5 * 60 * 1000) { try { // 进入等待的同时,会进入释放监视器 object.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; new Thread(task, "t1").start(); new Thread(task, "t2").start(); } }
可以发现t1和t2都处在WAITING (on object monitor),进入等待状态的原因是调用了in Object.wait()。通过J.U.C包下的锁和条件队列,也是这个效果,大家可以自己实践下。
3、显示TIMED_WAITING状态

public class TimedWaitingState { // java的显示锁,类似java对象内置的监视器 private static Lock lock = new ReentrantLock(); // 锁关联的条件队列(类似于object.wait) private static Condition condition = lock.newCondition(); public static void main(String[] args) { Runnable task = new Runnable() { @Override public void run() { // 加锁,进入临界区 lock.lock(); try { condition.await(5, TimeUnit.MINUTES); } catch (InterruptedException e) { e.printStackTrace(); } // 解锁,退出临界区 lock.unlock(); } }; new Thread(task, "t1").start(); new Thread(task, "t2").start(); } }
可以看到t1和t2线程都处在java.lang.Thread.State: TIMED_WAITING (parking),这个parking代表是调用的JUC下的工具类,而不是java默认的监视器。
五、如何使用interupt方法中断线程
代码:

public class GeneralInterrupt extends Object implements Runnable { public void run() { try { System.out.println("in run() - about to work2()"); work2(); System.out.println("in run() - back from work2()"); } catch (InterruptedException x) { System.out.println("in run() - interrupted in work2()"); return; } System.out.println("in run() - doing stuff after nap"); System.out.println("in run() - leaving normally"); } public void work2() throws InterruptedException { while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("C isInterrupted()=" + Thread.currentThread().isInterrupted()); Thread.sleep(2000); System.out.println("D isInterrupted()=" + Thread.currentThread().isInterrupted()); } } } public void work() throws InterruptedException { while (true) { for (int i = 0; i < 100000; i++) { int j = i * 2; } System.out.println("A isInterrupted()=" + Thread.currentThread().isInterrupted()); if (Thread.interrupted()) { System.out.println("B isInterrupted()=" + Thread.currentThread().isInterrupted()); throw new InterruptedException(); } } } public static void main(String[] args) { GeneralInterrupt si = new GeneralInterrupt(); Thread t = new Thread(si); t.start(); try { Thread.sleep(2000); } catch (InterruptedException x) { } System.out.println("in main() - interrupting other thread"); t.interrupt(); System.out.println("in main() - leaving"); } }
执行结果
in run() - about to work2()
in main() - interrupting other thread
in main() - leaving
C isInterrupted()=true
in run() - interrupted in work2()