线程(中)
发布日期:2021-05-06 03:20:44 浏览次数:19 分类:技术文章

本文共 7284 字,大约阅读时间需要 24 分钟。

线程的状态

在这里插入图片描述

start();启动线程 就绪状态(等待CPU的加载)

​ 当线程获得了CPU的执行权,进入到运行状态

​ 当线程失去CPU执行权(因为CPU需要轮流执行其他线程),进入待就绪状态

​ 当线程中所有任务执行完以后,进入死亡状态

yield();线程主动让步

sleep();让线程休眠指定时间,进入阻塞状态

t.join();线程合并,等待t进程执行完后,其他进程再执行

stop();强制让线程销毁

public class ThreadDemo extends Thread{       @Override    public void run() {           for (int i = 0; i <1000 ; i++) {               /*if (i%5==0){                Thread.yield();//线程主动让步            }*/          /*  try {                Thread.sleep(1000);//让线程休眠指定时间,进入阻塞状态            } catch (InterruptedException e) {                e.printStackTrace();            }*/            System.out.println(Thread.currentThread().getName()+":"+i);        }    }}
public class Test {       public static void main(String[] args) {           ThreadDemo threadDemo = new ThreadDemo();        threadDemo.setName("线程1");        threadDemo.start();//启动线程  就绪状态(等待CPU加载)                           // 当线程获得了CPU的执行权   ,进入到运行状态                            //当线程失去CPU执行权(因为CPU还要轮流执行其他线程),进入就绪状态                            //当线程中所有任务执行完以后,进入死亡状态       /* try {            threadDemo.join();//线程合并,等待threadDemo线程执行完后,其他线程执行        } catch (InterruptedException e) {            e.printStackTrace();        }*/        //threadDemo.stop();//强制让线程销毁        ThreadDemo threadDemo2 = new ThreadDemo();        threadDemo2.setName("线程2");        threadDemo2.start();//启动线程        //threadDemo2.stop();//强制让线程销毁    }}

守护线程

是一种特殊的线程

当把一个线程设置为守护线程时,守护线程需要等所有得非守护线程执行完结束后,才会销毁

t.setDaemon(true);将线程设置为守护线程

JVM中垃圾回收器就是一个典型的守护线程

public class ThreadDemo extends Thread{       @Override    public void run() {           while (true){               System.out.println("我是守护线程");        }    }}public class Test {       public static void main(String[] args) {           ThreadDemo threadDemo = new ThreadDemo();        threadDemo.setDaemon(true);//将线程设置为守护线程        threadDemo.start();//启动线程        for (int i = 0; i < 1000; i++) {               System.out.println("我是用户线程");        }    }}

线程的同步

并行:多个CPU同时执行多个任务

并发:一个CPU同时执行多个任务

前提:

1.必须是多线程

2.多线程访问同一个共享资源

同步机制:线程排队+锁

static 变量 随着类的加载而加载,生命周期长

非static 变量 生命周期与对象相同

典型案例:买票

票数是固定的,买票的窗口有多个,就有多个线程同时访问同一资源

使用synchronize修饰

通过两种创建线程的方法实现功能

一.继承Thread类

1.synchronize修饰同步代码块

public class VoteDemo extends Thread {       static int votes = 10;//多个线程访问共享资源    static Object obj = new Object();//创建唯一的锁    @Override    public void run() {       //while循环一直出票        while (true) {           //为需要同步的代码,用同步代码快修饰,多个线程只有一把锁,谁先拿到谁就用        //当持有锁的线程把同步代码中的内容执行完以后,离开同步代码快,会自动释放锁            synchronized (obj){                   if (votes > 0) {                       System.out.println(Thread.currentThread().getName() + ":" + votes);                    votes--;                } else if (votes <= 0) {                       break;                }            }        }    }

2.用synchronized修饰方法,此方法为同步方法

public class VoteDemo extends Thread {     static int votes = 10;//多个线程访问共享资源   @Override    public void run() {           while (true) {               if (votes > 0) {                   vote();            } else {                   break;            }        }    }	//用synchronized修饰方法,此方法为同步方法    //synchronized修饰方式时,锁对象默认为this,多个线程就有多把锁    public static synchronized void vote() {           if (votes > 0) {               System.out.println(Thread.currentThread().getName() + ":" + votes);            votes--;        }    }}

测试类

public class Test {       public static void main(String[] args) {           VoteDemo voteDemo = new VoteDemo();        voteDemo.setName("窗口1");        voteDemo.start();        VoteDemo voteDemo2 = new VoteDemo();        voteDemo2.setName("窗口2");        voteDemo2.start();    }}

二.实现Runnable类

1.synchronize修饰同步代码块

public class VoteDemo implements Runnable {       int votes = 10;    Object obj = new Object();    //修饰同步内容    @Override    public void run() {           while (true) {               synchronized (obj){                   if (votes > 0) {                       System.out.println(Thread.currentThread().getName() + ":" + votes);                    votes--;                } else if (votes <= 0) {                       break;                }            }        }    }}

2.用synchronized修饰方法,此方法为同步方法

public class VoteDemo implements Runnable {       int votes = 10;    Object obj = new Object();    @Override    public void run() {           while (true) {               if (votes > 0) {                   Vote();            } else {                   break;            }        }    }    //用synchronize修饰方法,此方法为同步方法    //synchronize修饰方法时,锁对象默认为this,只创建一个线程任务对象,this只有一个    public synchronized void Vote() {           if (votes > 0) {               System.out.println(Thread.currentThread().getName() + ":" + votes);            votes--;        }    }}

测试类

public class Test {       public static void main(String[] args) {           VoteDemo voteDemo = new VoteDemo();        Thread thread1 = new Thread(voteDemo);        Thread thread2 = new Thread(voteDemo);        thread1.setName("窗口1");        thread2.setName("窗口2");        thread1.start();        thread2.start();    }}

线程死锁

当线程持有对方线程中需要的锁时,会出现死锁现象

public class DieLock extends Thread {       static Object objA = new Object();    static Object objB = new Object();    boolean flag;    public DieLock(boolean flag) {           this.flag = flag;    }    @Override    public void run() {           if (flag){               synchronized (objA){                   System.out.println("if objA");//objA这把锁已经被使用                synchronized (objB){   //此时只能等待下面释放objB锁                    System.out.println("if objB");                }            }        }else{               synchronized (objB){                   System.out.println("else objB");//objB这把锁也被使用                synchronized (objA){   //此时等待上面释放objA锁                    System.out.println("else objA");                }            }        }    }}
public class Test {       public static void main(String[] args) {           DieLock t1= new DieLock(true);        DieLock t2= new DieLock(false);        t1.start();        t2.start();    }}

运行结果:

死锁出现不会报错,不会提示,只是等待.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DZyhn87e-1611997903680)(C:\Users\17509\AppData\Roaming\Typora\typora-user-images\1611204001419.png)]

Lock方式的加锁

JDK5之后使用Lock方式显示的加锁,释放锁

Lock是显式锁(手动开启和关闭锁,别忘记关闭锁), 实现类ReentrantLock

synchronized是隐式锁,出了作用域自动释放

Lock只有代码块锁

synchronized 有代码块锁,方法

import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class VoteDemo extends Thread {       static int num = 10;    static Lock lock = new ReentrantLock();//创建锁对象    @Override    public void run() {           while(true){               try {                   lock.lock();//获得锁,加锁                Thread.sleep(100);                if(num>0){                       System.out.println(num);                    num--;                }else{                       break;                }                lock.unlock();//释放锁            }catch (Exception e){                   e.printStackTrace();                lock.unlock();//释放锁            }        }    }}
public class Test {       public static void main(String[] args) {           VoteDemo voteDemo = new VoteDemo();        voteDemo.setName("窗口1");        voteDemo.start();        VoteDemo voteDemo2 = new VoteDemo();        voteDemo2.setName("窗口2");        voteDemo2.start();    }}
上一篇:线程(下)--线程通信&&消费者问题
下一篇:IO练习题--文件分割

发表评论

最新留言

感谢大佬
[***.8.128.20]2025年04月08日 23时47分01秒