Java并发编程之线程

手机软件开发 2024-9-20 07:22:18 112 0 来自 中国
Java多线程是为了更好使用CPU资源,提拔体系吞吐率,在一些得当的场合,用多线程可以制止壅闭。
一、线程简介

简单main函数检察线程信息(JDK11)
public class PrintThread {    public static void main(String[] args) {        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);        for (ThreadInfo threadInfo : threadInfos) {            System.out.println("["+threadInfo.getThreadId()+"] " + threadInfo.getThreadName());            //可以直接输出threadInfo 打印具体信息        }    }}输出:
[1] main                                         #主线程main,程序入口[2] Reference Handler                            #打扫Reference线程[3] Finalizer                                    #调用对象finalize方法的线程[4] Signal Dispatcher                            #分发处理处罚发给JVM信号的线程[12] Notification Thread.                        #JDK11才有[13] Common-Cleaner                              #JDK11才有相干假造机接口类MXBean,可检察JDK中java.lang.management包,好比
线程支持优先级设置setPriority(int), 范围1~10,默认优先级是5,优先级越高分配的时间片越多。有些操纵体系会忽略对线程优先级的设定,不保举使用
Daemon守护线程是一种支持型线程,负责背景调理大概支持工作。当假造机不存在非Daemon进程的时间,假造机将会退出。通过setDaemon(true)设置,只能在启动之前设置,否则抛非常。
线程状态(6种)

状态名称分析NEW初始状态,线程被构建,但还没有调用start方法RUNNABLE运行状态,Java线程把操纵体系的停当和运行两种状态笼统地称作"运行中"BLOCKED壅闭状态,表现线程壅闭于锁WAITING等候状态,进入该状态表现当火线程须要等候其它线程关照大概制止TIME_WAITING超时等候状态,差别于WAITING,它可以在指定的时间自行返回TERMINATED制止状态,表现当火线程已经实行完毕参考java.lang.Thread 中罗列类State
线程状态变迁图



  • wait/notify/notifyAll  Object对象的方法,必须跟synchronized搭配使用;且使用同一个锁对象;wait会开释锁,notify/notifyAll不会开释锁,等候线程真正唤醒要比及唤醒线程开释锁,并获取到锁,才真正唤醒;
  • join 等候线程实行竣事,Thread对象的方法,内部实现原理也是wait方式
public final void join() throws InterruptedException {        join(0);}public final synchronized void join(long millis)    throws InterruptedException {        ...        if (millis == 0) {            while (isAlive()) {                wait(0);            }        } else {           ...        }   }

  • LockSuppport.park()/unpark(Thread)  支持唤醒指定线程
public class ParkThread extends Thread{    @Override    public void run() {        System.out.println("doing....");        LockSupport.park(); //进入waiting        System.out.println("unpack continue doing...");    }    public static void main(String[] args) throws InterruptedException {        ParkThread parkThread = new ParkThread();        parkThread.start();        Thread.sleep(5000); //休眠5s        LockSupport.unpark(parkThread); //唤醒    }}

  • Thread.sleep(long)  休眠不开释锁, 时间到了主动唤醒
二、线程启动/制止/制止


  • 线程启动支持两种方式:(1)继续Thread (2)实现Runnable接口
class MyThread extends Thread{     public void run(){            ...     }}MyThread p = new MyThread();p.start();class MyJob implements Runable{     public void run(){         ...     }}new Thread(new MyJob()).start();

  • 优雅制止线程方式:自界说标记位和制止标记位
public class StopThread extends Thread{    private volatile boolean exit = false;    private long count = 0;    @Override    public void run() {        while (!exit && !Thread.currentThread().isInterrupted()){            count ++;        }        System.out.println(Thread.currentThread().getName()+ " count:" + count);    }    public void cancel(){        this.exit = true;    }    public static void main(String[] args) throws InterruptedException {       StopThread stopThread1 = new StopThread();       stopThread1.setName("FlagThread");       stopThread1.start();       StopThread stopThread2 = new StopThread();       stopThread2.setName("InterruptedThread");       stopThread2.start();       Thread.sleep(20);       stopThread1.cancel(); //自界说标记位       Thread.sleep(10);       stopThread2.interrupt();//制止标记位    }}
制止实在是一个标记位,当线程实行interrupt()方法,假如线程处于Runnable状态时,isInterrupted() 返回true,假如线程处于壅闭阶段,线程会抛InterruptedException,并重置制止标记位,所以isInterrupted() 返回false
线程stop()方法可以制止线程,但不保举使用,它是一个被废弃的方法,无法包管资源的完全开释。
线程停息suspend()和规复resume() 方法也是被废弃的方法,suspend() 不开释锁,容器导致死锁。
三、线程通讯

线程间通讯重要有共享变量消息转达
1.volatile

public class VolatileTest{        static volatile boolean flag = false; //界说共享变量,volatile修饰线程及时感知    public static void main(String[] args) throws InterruptedException{        List<String> list = new ArrayList<>();                Thread threadA = new Thread(()->{                for(int i = 1; i <= 10; i++){                    list.add("hello");                    System.out.println("线程A添加元素,size="+list.size());                    //Thread.sleep(1000);                    if(list.size()==5){ //线程A添加到第五个元素关照B线程                            flag = true;                    }                }        });        Thread threadB = new Thread(()->{                while(true){                    if(flag){                        System.out.println("线程B收到关照实行本身业务");                        break;                    }                }        });        threadB.start();        Thread.sleep(1000); //确保先启动threadB        threadA.start();    }}2.wait()/notify()

public class WaitNotifyTest{        public static void main(String[] args) throws InterruptedException{        Object lock = new Object();         List<String> list = new ArrayList<>();                Thread notifyThread = new Thread(()->{                synchronized(lock){                    for(int i = 1; i <= 10; i++){            list.add("hello");            System.out.println("NotityThread添加元素,size="+list.size());            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            if(list.size()==5){ //添加到第五个元素关照WaitThread                lock.notify();            }          }                }        });        Thread waitThread = new Thread(()->{                synchronized(lock){            if(list.size()!=5){                 try {                    lock.wait();             } catch (InterruptedException e) {                    e.printStackTrace();             }            }                    System.out.println("WaitThread收到关照实行本身业务");        }        });        waitThread.start();        Thread.sleep(1000); //确保先启动WaitThread        notifyThread.start();            }}
NotityThread线程固然调用notify()唤醒,依然是要走完本身业务,WaitThread线程才开始真正实行;由于notify()并没有开释锁,NotifyThread线程运行竣事开释锁,WaitThread线程获取锁才真正唤醒进入Runnable状态
3. ReentrantLock + Condition

public class NotifyThread{    public static void main(String[] args) throws InterruptedException{        ReentrantLock lock = new ReentrantLock();        Condition condition = lock.newCondition();        List<String> list = new ArrayList<>();        Thread notifyThread = new Thread(()->{            lock.lock();            try{                for(int i = 1; i <= 10; i++){                    list.add("hello");                    System.out.println("NotityThread添加元素,size="+list.size());                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    if(list.size()==5){ //添加到第五个元素关照WaitThread                        condition.signal();                    }                }            }finally {                lock.unlock();            }        });        Thread waitThread = new Thread(()->{            lock.lock();            try{                if(list.size()!=5){                    try {                        condition.await();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                System.out.println("WaitThread收到关照实行本身业务");            }finally {                lock.unlock();            }        });        waitThread.start();        Thread.sleep(1000); //确保先启动WaitThread        notifyThread.start();    }}
这种方法跟Object的wait()/notify() 一样,WaitThread线程要比及NotifyThread线程开释锁,才能真正唤醒。
2.png
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-25 09:21, Processed in 0.181607 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表