java线程的6种状态以及相互转换

简介: java多线程基础知识,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());
        
        
    }
}

执行结果

--继承thread--
--runnable没有返回值--
--callable有返回值--
test-callable

二、线程相关的方法

screenshot

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<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线程结束");
    }
}

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<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();
    }
}

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内存模型
screenshot
内存操作指令
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代码就是synchronized

volatile关键字的作用:
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) {
            }
        }
    }
    
    
    public static void main(String[] args) {
        map.put("thread1", "thread1");
        map.put("thread2", "thread2");
        new Thread(new Task1()).start();
        new Thread(new Task2()).start();
    }
}

运行结果

task2:{thread1=thread1, thread2=thread2}
task1:{thread1=thread1, thread2=thread2}
task2:{thread2=thread2}
task1:{thread2=thread2}
task1:{}
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状态
线程状态变化
_1

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等的实现已经线程管理的线程池的实现,正在整理中,敬请期待

相关文章
|
4天前
|
Java 程序员 开发者
深入理解Java并发编程:线程同步与锁机制
【4月更文挑战第30天】 在多线程的世界中,确保数据的一致性和线程间的有效通信是至关重要的。本文将深入探讨Java并发编程中的核心概念——线程同步与锁机制。我们将从基本的synchronized关键字开始,逐步过渡到更复杂的ReentrantLock类,并探讨它们如何帮助我们在多线程环境中保持数据完整性和避免常见的并发问题。文章还将通过示例代码,展示这些同步工具在实际开发中的应用,帮助读者构建对Java并发编程深层次的理解。
|
4天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第30天】本文将深入探讨Java并发编程中的一个重要主题——线程池。我们将从线程池的基本概念入手,了解其工作原理和优势,然后详细介绍如何使用Java的Executor框架创建和管理线程池。最后,我们将讨论一些高级主题,如自定义线程工厂和拒绝策略。通过本文的学习,你将能够更好地理解和使用Java的线程池,提高你的并发编程能力。
|
4天前
|
安全 Java 调度
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第30天】本文将深入探讨Java并发编程的核心概念,包括线程安全、同步机制、锁优化以及性能调优。我们将通过实例分析如何确保多线程环境下的数据一致性,同时介绍一些常见的并发模式和最佳实践,旨在帮助开发者在保证线程安全的同时,提升系统的性能和响应能力。
|
2天前
|
存储 缓存 前端开发
Java串口通信技术探究3:RXTX库线程 优化系统性能的SerialPortEventListener类
Java串口通信技术探究3:RXTX库线程 优化系统性能的SerialPortEventListener类
11 3
|
2天前
|
Java
JAVA难点包括异常处理、多线程、泛型和反射,以及复杂的分布式系统知识
JAVA难点包括异常处理、多线程、泛型和反射,以及复杂的分布式系统知识。入坑JAVA因它的面向对象特性、平台无关性、强大的标准库和活跃的社区支持。
12 2
|
2天前
|
Java 调度 开发者
Java中的多线程编程:基础与实践
【5月更文挑战第2天】本文将深入探讨Java中的多线程编程,从基础概念到实际应用,为读者提供全面的理解和实践指导。我们将首先介绍线程的基本概念和重要性,然后详细解析Java中实现多线程的两种主要方式:继承Thread类和实现Runnable接口。接着,我们将探讨线程同步的问题,包括synchronized关键字和Lock接口的使用。最后,我们将通过一个实际的生产者-消费者模型来演示多线程编程的实践应用。
|
2天前
|
安全 Java 程序员
Java中的多线程编程:从理论到实践
【5月更文挑战第2天】 在计算机科学中,多线程编程是一项重要的技术,它允许多个任务在同一时间段内并发执行。在Java中,多线程编程是通过创建并管理线程来实现的。本文将深入探讨Java中的多线程编程,包括线程的概念、如何创建和管理线程、以及多线程编程的一些常见问题和解决方案。
11 1
|
3天前
|
存储 安全 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第1天】本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化。我们将详细分析线程安全问题的根源,以及如何通过合理的设计和编码实践来避免常见的并发问题。同时,我们还将探讨如何在保证线程安全的前提下,提高程序的并发性能,包括使用高效的同步机制、减少锁的竞争以及利用现代硬件的并行能力等技术手段。
|
3天前
|
并行计算 Java 数据处理
Java中的多线程编程:基础知识与实践
【5月更文挑战第1天】本文将深入探讨Java中的多线程编程,包括其基本概念、实现方式以及实际应用。我们将从理论和实践两个角度出发,详细解析线程的创建、启动、控制以及同步等关键问题,并通过实例代码演示如何在Java中有效地使用多线程。
|
3天前
|
Java 程序员
Java中的多线程编程:从理论到实践
【5月更文挑战第1天】 在现代计算机科学中,多线程编程是一个重要的概念,它允许程序员在同一程序中并行运行多个任务。Java作为一种广泛使用的编程语言,提供了一套丰富的多线程编程工具。本文将介绍Java中多线程编程的基本概念,包括线程的创建、启动、控制和同步,以及一些常见的多线程问题和解决方案。