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

相关文章
|
9天前
|
安全 Java 数据处理
Java并发编程:解锁多线程的潜力
在数字化时代的浪潮中,Java作为一门广泛使用的编程语言,其并发编程能力是提升应用性能和响应速度的关键。本文将带你深入理解Java并发编程的核心概念,探索如何通过多线程技术有效利用计算资源,并实现高效的数据处理。我们将从基础出发,逐步揭开高效并发编程的面纱,让你的程序运行得更快、更稳、更强。
|
8天前
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
30 7
|
6天前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
6天前
|
存储 监控 安全
一天十道Java面试题----第三天(对线程安全的理解------>线程池中阻塞队列的作用)
这篇文章是Java面试第三天的笔记,讨论了线程安全、Thread与Runnable的区别、守护线程、ThreadLocal原理及内存泄漏问题、并发并行串行的概念、并发三大特性、线程池的使用原因和解释、线程池处理流程,以及线程池中阻塞队列的作用和设计考虑。
|
2天前
|
Java
java开启线程的四种方法
这篇文章介绍了Java中开启线程的四种方法,包括继承Thread类、实现Runnable接口、实现Callable接口和创建线程池,每种方法都提供了代码实现和测试结果。
java开启线程的四种方法
|
4天前
|
存储 缓存 安全
深度剖析Java HashMap:源码分析、线程安全与最佳实践
深度剖析Java HashMap:源码分析、线程安全与最佳实践
|
10天前
|
消息中间件 Java 大数据
"深入理解Kafka单线程Consumer:核心参数配置、Java实现与实战指南"
【8月更文挑战第10天】在大数据领域,Apache Kafka以高吞吐和可扩展性成为主流数据流处理平台。Kafka的单线程Consumer因其实现简单且易于管理而在多种场景中受到欢迎。本文解析单线程Consumer的工作机制,强调其在错误处理和状态管理方面的优势,并通过详细参数说明及示例代码展示如何有效地使用KafkaConsumer类。了解这些内容将帮助开发者优化实时数据处理系统的性能与可靠性。
38 7
|
7天前
|
安全 Java
Java模拟生产者-消费者问题。生产者不断的往仓库中存放产品,消费者从仓库中消费产品。其中生产者和消费者都可以有若干个。在这里,生产者是一个线程,消费者是一个线程。仓库容量有限,只有库满时生产者不能存
该博客文章通过Java代码示例演示了生产者-消费者问题,其中生产者在仓库未满时生产产品,消费者在仓库有产品时消费产品,通过同步机制确保多线程环境下的线程安全和有效通信。
|
5天前
|
缓存 前端开发 JavaScript
一篇文章助你搞懂java中的线程概念!纯干货,快收藏!
【8月更文挑战第11天】一篇文章助你搞懂java中的线程概念!纯干货,快收藏!
17 0
一篇文章助你搞懂java中的线程概念!纯干货,快收藏!
|
7天前
|
缓存 监控 Java
Java性能优化:从单线程执行到线程池管理的进阶实践
在Java开发中,随着应用规模的不断扩大和用户量的持续增长,性能优化成为了一个不可忽视的重要课题。特别是在处理大量并发请求或执行耗时任务时,单线程执行模式往往难以满足需求,这时线程池的概念便应运而生。本文将从应用场景举例出发,探讨Java线程池的使用,并通过具体案例和核心代码展示其在实际问题解决中的强大作用。
23 1