线程如何创建
创建线程有三种方式:继承Thread类;无返回值的Runnable;有返回值的Callable
示例如下
package com.rcl.platform.demo; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CreateThread { public static class TestThread extends Thread { @Override public void run() { System.out.println("--继承thread--"); } } public static class TestRunnable implements Runnable { @Override public void run() { System.out.println("--runnable没有返回值--"); } } public static class TestCallable implements Callable<String> { @Override public String call() throws Exception { System.out.println("--callable有返回值--"); return "test-callable"; } } public static void main(String[] args) throws InterruptedException, ExecutionException { Thread thread = new Thread(new TestThread()); thread.start(); thread = new Thread(new TestRunnable()); thread.start(); FutureTask<String> ft = new FutureTask<>(new TestCallable()); thread = new Thread(ft); thread.start(); System.out.println(ft.get()); } }
执行结果
--继承thread-- --runnable没有返回值-- --callable有返回值-- test-callable
线程相关的基础方法
wait:获取锁对象monitor的线程执行wait方法,将会释放对monitor的控制权,其他线程可以获取到锁对象的monitor,执行notify唤醒wait线程
notify/notifyall:获取到monitor,唤醒曾经获取到monitor执行wait正在处于等待的线程(线程状态为WAITING,TIMED_WAITING)
sleep:线程休眠
yield:yield方法的作用是暂停当前线程,以便其他线程有机会执行,不过不能指定暂停的时间,并且也不能保证当前线程马上停止。yield方法只是将Running状态转变为Runnable状态(不能完全保证,最好少用)
join:join方法的作用是父线程等待子线程执行完成后再执行,换句话说就是将异步执行的线程合并为同步的线程,如:如果在mian线程执行的过程中执行t1.join方法,那么将转而执行t1线程,t1线程执行完毕后执行mian线程
package com.rcl.platform.demo; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; public class JoinTest { public static class TestThread extends Thread { @Override public void run() { for(int i=0; i<10; i++){ System.out.println("第" + i + "次执行"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws InterruptedException, ExecutionException { TestThread thread = new TestThread(); thread.start(); thread.join(); System.out.println("等待thread执行完毕后main线程结束"); } }
执行结果
第0次执行 第1次执行 第2次执行 第3次执行 第4次执行 第5次执行 第6次执行 第7次执行 第8次执行 第9次执行 等待thread执行完毕后main线程结束
interrupt:他的作用是“停止”当前线程的运行,为什么加上一个引号,它只在特殊情况下有用,像线程调用了wait,sleep,join等可中断的阻塞方法 后,调用interrupt就会抛出InterruptedException异常。其实它称为协作停止。调用了这个方法后线程除了特殊情况外别的时候并不会停止,它发送一个停止请求,并且由线程记录下来(实际上就是有一个为bool的变量,当为true时就表示有停止线程运行请求)。所以说线程真正的停止需要我们自己去检查是否有停止线程的请求,当有线程停止请求时停用当前线程。和他配套是使用的有
public static boolean interrupted()
public boolean isInterrupted()
package com.rcl.platform.demo; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; public class JoinTest { public static class TestThread extends Thread { @Override public void run() { for(int i=0; i<1000000000; i++){ System.out.println("TestThread第" + i + "次执行"); if(Thread.interrupted()){ return; } } } } public static class TestThreadSleep extends Thread { @Override public void run() { for(int i=0; i<10; i++){ System.out.println("TestThreadSleep第" + i + "次执行"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } if(Thread.interrupted()){ return; } } } } public static void main(String[] args) throws InterruptedException, ExecutionException { TestThread thread = new TestThread(); thread.start(); thread.interrupt(); TestThreadSleep threadSleep = new TestThreadSleep(); threadSleep.start(); threadSleep.interrupt(); } }
执行结果
TestThread第0次执行 TestThreadSleep第0次执行 java.lang.InterruptedException: sleep interruptedTestThreadSleep第1次执行 at java.lang.Thread.sleep(Native Method) at java.lang.Thread.sleep(Thread.java:340) at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) at com.rcl.platform.demo.JoinTest$TestThreadSleep.run(JoinTest.java:27) TestThreadSleep第2次执行 TestThreadSleep第3次执行 TestThreadSleep第4次执行 TestThreadSleep第5次执行 TestThreadSleep第6次执行 TestThreadSleep第7次执行 TestThreadSleep第8次执行 TestThreadSleep第9次执行
线程状态
1、java线程有6中状态,分别为NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED详解java.lang.Thread$State枚举类
2、线程初始化为NEW状态,该状态表示还未调用start方法
3、执行线程调用start方法,线程状态转换为RUNNABLE(包括竞争到CPU时间真正意义的执行和没有竞争到CPU时间等待下一个CPU时间的状态)
4、BLOCKED状态为锁竞争,没有竞争到锁为BLOCKED,等待拥有锁的线程释放锁,进入RUNNABLE状态
5、WAITING状态为竞争到锁,执行wait方法,又释放锁,本线程进入WAITING,等待其他线程唤醒notify,notifyall,如果不唤醒,将一直处于WAITING状态
6、TIMED_WAITING为执行sleep join或者有时限的等待
7、线程执行完毕,线程处于TERMINATED状态
线程状态变化
package com.rcl.platform.demo; import java.util.concurrent.TimeUnit; public class ThreadState { public static void main( String[] args ) throws InterruptedException { System.out.println("-------------NEW-------------"); Thread thread = new Thread(); System.out.println(thread.getState() + ":" + (thread.getState() == Thread.State.NEW)); System.out.println("-------------分割线-------------"); System.out.println("-------------RUNNABLE、TERMINATED-------------"); thread = new Thread(new Runnable() { public void run() { System.out.println(Thread.currentThread().getState() + ":" + (Thread.currentThread().getState() == Thread.State.RUNNABLE)); } }); thread.start(); TimeUnit.SECONDS.sleep(1); System.out.println(thread.getState() + ":" + (thread.getState() == Thread.State.TERMINATED)); System.out.println("-------------分割线-------------"); System.out.println("-------------RUNNABLE、TIMED_WAITING-------------"); thread = new Thread(new Runnable() { public void run() { System.out.println(Thread.currentThread().getState() + ":" + (Thread.currentThread().getState() == Thread.State.RUNNABLE)); System.out.println("sleep 进入 TIMED_WAITING"); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); TimeUnit.SECONDS.sleep(1); System.out.println(thread.getState() ); TimeUnit.SECONDS.sleep(2); System.out.println("-------------分割线-------------"); System.out.println("-------------RUNNABLE、TIMED_WAITING-------------"); final Thread mainThread = Thread.currentThread(); thread = new Thread(new Runnable() { public void run() { System.out.println(Thread.currentThread().getState() + ":" + (Thread.currentThread().getState() == Thread.State.RUNNABLE)); try { System.out.println("join 进入 TIMED_WAITING"); System.out.println("mainThread: " + mainThread.getState()); TimeUnit.SECONDS.timedJoin(mainThread, 2);//先执行mainthread System.out.println("mainThread: " + mainThread.getState()); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); TimeUnit.SECONDS.sleep(1); System.out.println("testThread: " + thread.getState() ); System.out.println("-------------分割线-------------"); System.out.println("-------------RUNNABLE、WAITING-------------"); Object lock = new Object(); final Thread mainThread1 = Thread.currentThread(); thread = new Thread(new Runnable() { public void run() { synchronized (lock) { try { System.out.println("wait 进入 WAITING"); lock.wait(); System.out.println("mainThread1: " + mainThread1.getState() ); } catch (InterruptedException e) { e.printStackTrace(); } } } }); thread.start(); TimeUnit.SECONDS.sleep(1); System.out.println("testThread: " + thread.getState() ); synchronized (lock) { lock.notifyAll(); } TimeUnit.SECONDS.sleep(1); System.out.println("-------------分割线-------------"); Thread thread1 = new Thread(new Runnable() { public void run() { synchronized (lock) { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } }); thread1.start(); Thread thread2 = new Thread(new Runnable() { public void run() { synchronized (lock) { } } }); thread2.start(); TimeUnit.SECONDS.sleep(1); System.out.println("thread2: " + thread2.getState() ); } }
执行结果
-------------NEW------------- NEW:true -------------分割线------------- -------------RUNNABLE、TERMINATED------------- RUNNABLE:true TERMINATED:true -------------分割线------------- -------------RUNNABLE、TIMED_WAITING------------- RUNNABLE:true sleep 进入 TIMED_WAITING TIMED_WAITING -------------分割线------------- -------------RUNNABLE、TIMED_WAITING------------- RUNNABLE:true join 进入 TIMED_WAITING mainThread: TIMED_WAITING testThread: TIMED_WAITING -------------分割线------------- -------------RUNNABLE、WAITING------------- wait 进入 WAITING mainThread: TIMED_WAITING testThread: WAITING mainThread1: TIMED_WAITING -------------分割线------------- thread2: BLOCKED
欢迎加入学习交流群569772982,大家一起学习交流。