java线程的6种状态以及相互转换
一、线程如何创建
创建线程有三种方式:继承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());二、线程相关的方法
join示例
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 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线程结束");join执行结果
第0次执行 第1次执行 第2次执行 第3次执行 第4次执行 第5次执行 第6次执行 第7次执行 第8次执行 第9次执行 等待thread执行完毕后main线程结束interrupte示例
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 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(); }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次执行三、锁与monitor
java多线程执行的过程中,为了保证共享变量的线程安全,在多线程对共享变量的访问中需要对共享变量进行加锁操作加锁的形式主要表现为如下三种形式:同步方法、静态同步方法、同步块。
同步方法锁的是调用该方法的对象,为对象锁
静态同步方法是类锁,锁的是该类的class对象
同步块为对象锁,锁的synchronize中的对象
示例package com.rcl.platform.demo; public class ThreadState { public static synchronized void read(){ System.out.println("--这里是类锁--"); public synchronized void write(){ System.out.println("--这里是对象锁,锁定的是this对象--"); public static void main(String[] args) { Object lock = new Object(); synchronized (lock) { System.out.println("--这里是对象锁,锁定的是lock对象--"); }关于monitor更深层次的讲解参见:http://blog.csdn.net/jingzi123456789/article/details/69951057
四、谈谈volatile
谈到volatile,绕不开的话题还有java内存模型和java编译的重排优化机制java内存模型
内存操作指令
1)lock,作用于主内存变量,把一个变量标记为线程独占。
2)unlock,与lock正相反。
3)read,作用于主内存变量,它把一个变量从主内存传输到工作内存中。
4)load,作用于工作内存变量,把从read里面获取的变量放入工作内存的变量副本中。
5)use,作用于工作内存变量,把变量的值传递给执行引擎。
6)assign,作用于工作内存变量,把执行引擎的值 复制给工作内存变量。同use相反
7)store,作用于工作内存变量,把工作内存变量传输到主内存中。
8)write,作用于主内存变量,把store获取的值,写入到住内存中的变量。read load, store write成对出现
lock unlock指令来保证代码的原子性。反映到java代码就是synchronizedvolatile关键字的作用:
1)用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新.当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的.但是volatile 不能保证线程是安全的,因为java里面的运算并非原子操作。
2)volatile还有一个特性就是保证指令不重新排序。现在编译器,为了优化代码,都会重新排序指令。如果在多个线程里面,就会有很大的问题。volatile只能保证局部有序volatile boolean am= false; public void run() { context = read(); write(context); am= true; say(); cry(); }只能保证1,2在3之前,4、5在3之后
五、ThreadLocal线程本地变量
使用场景:ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了线程保持对象的方法和避免参数传递的方便的对象访问方式
源码分析//ThreadLocal 中的 set方法,往线程本地变量设置值,实质上值是存储在一个叫ThreadLocalMap中 public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); //有此可见,该Map直接存储在Thread本地,与其他线程隔离 void createMap(Thread t, T firstValue) { t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue); }线程本地变量解决不了共享变量问题,只是在线程中开辟了一块空间存储于该线程相关的变量,其他线程无法访问到该线程的本地变量,但是对于变量在线程初始化以前就已经初始化后在绑定到多个线程的线程本地变量中,无法解决共享问题。
示例package com.rcl.platform.demo; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; public class ThreadState { static Map String, String map = new HashMap (); static class Task1 implements Runnable { ThreadLocal Map String,String threadlocal = new ThreadLocal (); @Override public void run() { try { threadlocal.set(map); TimeUnit.SECONDS.sleep(1); System.out.println("task1:" + map); map.remove("thread1"); TimeUnit.SECONDS.sleep(1); System.out.println("task1:" + map); map = new HashMap (); TimeUnit.SECONDS.sleep(1); System.out.println("task1:" + map); } catch (InterruptedException e) { static class Task2 implements Runnable { ThreadLocal Map String,String threadlocal = new ThreadLocal (); @Override public void run() { try { threadlocal.set(map); TimeUnit.SECONDS.sleep(1); System.out.println("task2:" + map); TimeUnit.SECONDS.sleep(1); System.out.println("task2:" + map); TimeUnit.SECONDS.sleep(1); System.out.println("task2:" + map); } catch (InterruptedException e) {
task2:{}六、线程状态转换
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关于多线程,jdk提供了java.util.concurrent包的多线程解决方案,里面包含原子变量,线程安全的Map,Queue等的实现已经线程管理的线程池的实现,正在整理中,敬请期待
Java多线程基础(线程与进程的区别,线程的创建方式及常用api,线程的状态) 每一个线程都是一个执行流,都按照自己的顺序执行自己的代码,多个线程之间“同时”(并发并行)的执行多份代码。Java中的线程是以轻量级进程来实现的。
相关文章
- JAVA已过气?中俄大佬对话告诉你俄罗斯最受欢迎的编程语言是什么!
- Java BigDecimal toString() 的转换和输出
- java多线程状态转换
- Java Nashorn--Part 6
- java-BigDecimal百位取整和科学记数法转换
- Java 与 Json的互相转换
- java PriorityQueue(优先级队列)
- Java字符串转换为日期和时间比较大小
- Java enum的用法详解
- Java精选笔记_多线程(创建、生命周期及状态转换、调度、同步、通信)
- java对象与json对象间的相互转换
- 转:Java中String与byte[]的转换
- java玩转数据结构02 数组上
- Java 数据类型及转换
- Java IO(6) 字节流与字符流转换 InputStreamReader和OutputStreamWriter实现文件拷贝
- 使用JAXB来实现Java合xml之间的转换
- Java使用Cipher类实现加密,包括DES,DES3,AES和RSA加密
- 通过反射将一个java对象的属性值转换为一个Map
- 【Mysql系列】jsqlparser学习-SQL转换为java类