zoukankan      html  css  js  c++  java
  • 线程池详解_3

    1: 同步方法

     1 package Thread;
     2 
     3 /**
     4  * author liulei
     5  * data
     6  * since 1.8
     7  * version 1.0
     8  * Description 方法锁
     9  */
    10 //不安全的买票
    11 public class Test17 {
    12     public static void main(String[] args) {//出现同一张票被多次购买
    13         BuyTicket t = new BuyTicket();
    14         new Thread(t,"a").start();
    15         new Thread(t,"b").start();
    16         new Thread(t,"c").start();
    17     }
    18 }
    19 class BuyTicket implements Runnable{
    20     private int ticketNum = 10;
    21     Boolean flag =true;//外部停止方式
    22     @Override
    23     public void run() {
    24         try {
    25             Thread.sleep(10);
    26         } catch (InterruptedException e) {
    27             e.printStackTrace();
    28         }
    29         while (flag){
    30             try {
    31                 buy();
    32             } catch (InterruptedException e) {
    33                 e.printStackTrace();
    34             }
    35         }
    36     }
    37     private synchronized void buy() throws InterruptedException {//每个对象对应一把锁,这把锁就是this,
    38         if(ticketNum <= 0){
    39             flag = false;
    40             return;
    41         }
    42         Thread.sleep(100);
    43         System.out.println(Thread.currentThread().getName() + "拿到" + ticketNum--);
    44 
    45     }
    46 
    47 
    48 }

    2: 同步块

     1 package Thread;
     2 
     3 /**
     4  * author liulei
     5  * data
     6  * since 1.8
     7  * version 1.0
     8  * Description  同步块
     9  */
    10 public class Test18 {
    11     public static void main(String[] args) {
    12         Account account = new Account(100,"结婚基金");
    13         Drawing you = new Drawing(account, 50, "");
    14         Drawing girl = new Drawing(account, 100, "");
    15         you.start();
    16         girl.start();//可能导致多取钱
    17     }
    18 }
    19 class Account{
    20     int money;//余额
    21     String name;//卡名
    22 
    23     public Account(int money, String name) {
    24         this.money = money;
    25         this.name = name;
    26     }
    27 }
    28 //银行,模拟取款
    29 class Drawing extends Thread{
    30     Account account;//账户
    31     //取了多少钱
    32     int drawingMoney;
    33     //现在手里有多少钱
    34     int nowmoney;
    35 
    36 
    37     public Drawing(Account account, int drawingMoney, String name) {
    38         super(name);
    39         this.account = account;
    40         this.drawingMoney = drawingMoney;
    41 
    42     }
    43 
    44     @Override
    45     public void run() {//使用代码块加锁还不是在放上上是因为this是Drawing,而真正需要锁的对象是account
    46         synchronized (account){
    47             if(account.money-drawingMoney<0){
    48                 System.out.println(Thread.currentThread().getName() + "钱不够取不了");
    49                 return;
    50             }
    51             account.money -=drawingMoney;
    52             nowmoney += drawingMoney;
    53             System.out.println(account.name + "余额为" + account.money);
    54             System.out.println(this.getName()+"手里的钱" + nowmoney);
    55         }
    56         try {
    57             Thread.sleep(100);
    58         } catch (InterruptedException e) {
    59             e.printStackTrace();
    60         }
    61     }
    62 }
     1 package Thread;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 /**
     7  * author liulei
     8  * data   5.25
     9  * since 1.8
    10  * version 1.0
    11  * Description  不安全线程3
    12  */
    13 public class Test19 {
    14     public static void main(String[] args) throws InterruptedException {
    15         List<String> list = new ArrayList<String>();
    16         for (int i = 0; i < 10000; i++) {
    17             synchronized (list){//对多个线程共同处理的list进行加锁
    18                 new Thread(()->{
    19                     list.add(Thread.currentThread().getName());
    20                 }).start();
    21             }
    22         }
    23         Thread.sleep(100);
    24         System.out.println(list.size());//总数可能少于10000
    25     }
    26 
    27 }
    package Thread;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CopyOnWriteArrayList;
    
    /**
     * author liulei
     * data
     * since 1.8
     * version 1.0
     * Description  测试JUC安全类型的集合
     */
    public class Test20 {
        public static void main(String[] args) throws InterruptedException {
            CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();//本身是对list的升级,已经保证了线程安全性,不需要加锁
            for (int i = 0; i < 10000; i++) {
                    new Thread(()->{
                        list.add(Thread.currentThread().getName());
                    }).start();
            }
            Thread.sleep(100);
            System.out.println(list.size());//总数可能少于10000
        }
    }

    深入理解使用synchronized同步方法和同步代码块的区别

    同步方法对于当前对象this是要多个线程工作操作的对象时可以用同步方法,当然可以用代码块替代。否则要用同步代码块,把进行增删改的对象作为锁。

    方式一:同步代码块:
            synchronized(同步监视器){
                //操作共享数据的代码
            }
        注:1.同步监视器:俗称锁,任何一个类的对象都可以才充当锁。要想保证线程的安全,必须要求所有的线程共用同一把锁!
              2.使用实现Runnable接口的方式创建多线程的话,同步代码块中的锁,可以考虑是this。如果使用继承Thread类的方式,慎用this!
              3.共享数据:多个线程需要共同操作的变量。   明确哪部分是操作共享数据的代码。
    
    方式二:同步方法:将操作共享数据的方法声明为synchronized。
            比如:public synchronized void show(){ //操作共享数据的代码}
        注:1.对于非静态的方法而言,使用同步的话,默认锁为:this。如果使用在继承的方式实现多线程的话,慎用!
              2.对于静态的方法,如果使用同步,默认的锁为:当前类本身。以单例的懒汉式为例。 Class clazz = Singleton.class
            
    总结:释放锁:wait();
        不释放锁: sleep()   yield()  suspend() (过时,可能导致死锁)

    3: 死锁

     1 package Thread;
     2 
     3 /**
     4  * author liulei
     5  * data  5.25
     6  * since 1.8
     7  * version 1.0
     8  * Description 死锁:多个线程互相抱着对方需要的资源,形成僵持
     9  */
    10 public class Test21 {
    11     public static void main(String[] args) {
    12         Makeup makeup = new Makeup(0,"李雷");
    13         Makeup makeup1 = new Makeup(1,"韩梅梅");
    14         makeup.start();
    15         makeup1.start();
    16     }
    17 }
    18 //口红
    19 class Lipstick{
    20 
    21 }
    22 //镜子
    23 class Mirror{
    24 
    25 }
    26 class Makeup extends Thread{
    27     //需要的资源只有一份,用static来保证只有一份
    28     static Lipstick lipstick = new Lipstick();
    29     static Mirror mirror = new Mirror();
    30     int choice;//选择
    31     String girlName;//使用
    32 
    33     public Makeup(int choice, String girlName) {
    34         this.choice = choice;
    35         this.girlName = girlName;
    36     }
    37 
    38     @Override
    39     public void run() {
    40         try {
    41             makeup();
    42         } catch (InterruptedException e) {
    43             e.printStackTrace();
    44         }
    45     }
    46     private void makeup() throws InterruptedException {
    47         if(choice == 0){//李雷获得口红的锁,韩梅梅获得镜子的锁,但李雷韩梅梅希望获取对方的锁,但又不愿意释放自己的锁,形成死锁
    48             synchronized (lipstick){
    49                 System.out.println(this.girlName + "获得口红的锁");
    50                 Thread.sleep(100);
    51                 synchronized (mirror){
    52                     System.out.println(this.girlName + "获得镜子的锁");
    53                 }
    54             }
    55 
    56         }
    57         if(choice == 1){
    58             synchronized (mirror){
    59                 System.out.println(this.girlName + "获得镜子的锁");
    60                 Thread.sleep(100);
    61                 synchronized (lipstick){
    62                     System.out.println(this.girlName + "获得口红的锁");
    63                 }
    64             }
    65 
    66         }
    67     }
    68 }

    解决死锁

    package Thread;
    
    /**
     * author liulei
     * data  5.25
     * since 1.8
     * version 1.0
     * Description  解决死锁的一个方法就是用完自己的锁后释放
     */
    public class Test22 {
        public static void main(String[] args) {
            Makeup1 makeup = new Makeup1(0,"李雷");
            Makeup1 makeup1 = new Makeup1(1,"韩梅梅");
            makeup.start();
            makeup1.start();
        }
    }
    //口红
    class Lipstick1{
    
    }
    //镜子
    class Mirror1{
    
    }
    class Makeup1 extends Thread{
        //需要的资源只有一份,用static来保证只有一份
        static Lipstick lipstick = new Lipstick();
        static Mirror mirror = new Mirror();
        int choice;//选择
        String girlName;//使用
    
        public Makeup1(int choice, String girlName) {
            this.choice = choice;
            this.girlName = girlName;
        }
    
        @Override
        public void run() {
            try {
                makeup();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        private void makeup() throws InterruptedException {
            if(choice == 0){//李雷获得口红的锁,韩梅梅获得镜子的锁,但李雷韩梅梅希望获取对方的锁,但又不愿意释放自己的锁,形成死锁
                synchronized (lipstick){
                    System.out.println(this.girlName + "获得口红的锁");
                    Thread.sleep(100);
                }
                synchronized (mirror){
                    System.out.println(this.girlName + "获得镜子的锁");
                }
    
            }
            if(choice == 1){
                synchronized (mirror){
                    System.out.println(this.girlName + "获得镜子的锁");
                    Thread.sleep(100);
                }
                synchronized (lipstick){
                    System.out.println(this.girlName + "获得口红的锁");
                }
    
            }
        }
    }

    4: Lock

     1 package Thread;
     2 
     3 import java.util.concurrent.locks.ReentrantLock;
     4 
     5 /**
     6  * author liulei
     7  * data  5.25
     8  * since 1.8
     9  * version 1.0
    10  * Description lock锁
    11  */
    12 public class Test23 {
    13     public static void main(String[] args) {
    14         TestLock testLock = new TestLock();
    15         new Thread(testLock).start();
    16     }
    17 }
    18 class TestLock implements Runnable{
    19     int ticketNum = 10;
    20     private final ReentrantLock lock = new ReentrantLock();
    21     @Override
    22     public void run() {
    23         while (true){
    24             try{
    25                 lock.lock();//加锁
    26                 if(ticketNum > 0){
    27                     try {
    28                         Thread.sleep(1000);
    29                     } catch (InterruptedException e) {
    30                         e.printStackTrace();
    31                     }
    32                     System.out.println(ticketNum--);
    33                 }else{
    34                     break;
    35                 }
    36             }finally {
    37                 lock.unlock();//解锁
    38             }
    39         }
    40     }
    41 }

    5: 线程通信

     

     

     

     1 package Thread;
     2 
     3 /**
     4  * author liulei
     5  * data   5.25
     6  * since 1.8
     7  * version 1.0
     8  * Description  线程通信,生产者消费者(管程)
     9  */
    10 public class Test24 {
    11     public static void main(String[] args) {
    12         SynContainer synContainer = new SynContainer();
    13         new consumer(synContainer).start();
    14         new product(synContainer).start();
    15 
    16     }
    17 }
    18 class product extends Thread{
    19     SynContainer synContainer;
    20 
    21     public product(SynContainer synContainer) {
    22         this.synContainer = synContainer;
    23     }
    24 
    25     @Override
    26     public void run() {
    27         for (int i = 0; i < 100; i++) {
    28 
    29             try {
    30                 synContainer.push(new Chicken(i));
    31             } catch (InterruptedException e) {
    32                 e.printStackTrace();
    33             }
    34             System.out.println("生产者生产第" + (i+1) + "只鸡");
    35         }
    36     }
    37 }
    38 class consumer extends Thread{
    39     SynContainer synContainer;
    40 
    41     public consumer(SynContainer synContainer) {
    42         this.synContainer = synContainer;
    43     }
    44 
    45     @Override
    46     public void run() {
    47         for (int i = 0; i < 100; i++) {
    48             try {
    49                 System.out.println("消费者消费了第" + (synContainer.pop().id+1) + "只鸡");
    50             } catch (InterruptedException e) {
    51                 e.printStackTrace();
    52             }
    53         }
    54         try {
    55             synContainer.pop();
    56         } catch (InterruptedException e) {
    57             e.printStackTrace();
    58         }
    59     }
    60 }
    61 class Chicken{
    62     int id;
    63 
    64     public Chicken(int id) {
    65         this.id = id;
    66     }
    67 }
    68 class SynContainer{
    69     Chicken[] chickens = new Chicken[10];//容器大小
    70     int count = 0;//容器计数器
    71     //生产者放入产品
    72     public synchronized void push(Chicken chicken) throws InterruptedException {
    73         if(count == chickens.length){
    74             //通知消费者消费,生产等待
    75             wait();
    76         }
    77         chickens[count] = chicken;
    78         count++;
    79         //可以通知消费者消费了
    80         notify();
    81     }
    82     //消费者消费产品
    83     public synchronized Chicken pop() throws InterruptedException {
    84         //判断能否消费
    85         if(count == 0){
    86             //等待生产者生产,消费者等待
    87             wait();
    88         }
    89         //可以消费了
    90         count--;
    91         Chicken chicken = chickens[count];
    92         //吃完了,通知生产者生产
    93         notify();
    94         return chicken;
    95     }
    96 }
     1 package Thread;
     2 
     3 /**
     4  * author liulei
     5  * data  5.25
     6  * since 1.8
     7  * version 1.0
     8  * Description  演员和观众(信号量)
     9  */
    10 public class Test25 {
    11     public static void main(String[] args) {
    12         TV tv = new TV();
    13         new Player(tv).start();
    14         new Watcher(tv).start();
    15     }
    16 }
    17 //生产者-->演员
    18 class Player extends Thread{
    19     TV tv;
    20 
    21     public Player(TV tv) {
    22         this.tv = tv;
    23     }
    24 
    25     @Override
    26     public void run() {
    27         for (int i = 0; i < 10; i++) {
    28             if(i%2 == 0){
    29                 try {
    30                     this.tv.play("梦想中国节目");
    31                 } catch (InterruptedException e) {
    32                     e.printStackTrace();
    33                 }
    34             }else{
    35                 try {
    36                     this.tv.play("天天向上节目");
    37                 } catch (InterruptedException e) {
    38                     e.printStackTrace();
    39                 }
    40             }
    41         }
    42     }
    43 }
    44 //消费者-->观众
    45 class Watcher extends Thread{
    46     TV tv;
    47 
    48     public Watcher(TV tv) {
    49         this.tv = tv;
    50     }
    51 
    52     @Override
    53     public void run() {
    54         try {
    55             for (int i = 0; i < 10; i++) {
    56                 tv.watch();
    57             }
    58         } catch (InterruptedException e) {
    59             e.printStackTrace();
    60         };
    61     }
    62 }
    63 //产品-->节目
    64 class  TV{
    65     //演员表演,观众等待
    66     //观众观看,演员等待
    67     String voice;
    68     boolean flag = true;//没有节目了
    69     //表演
    70     public synchronized void play(String voice) throws InterruptedException {
    71         if(!flag){
    72             wait();
    73         }
    74         System.out.println("演员表演了" + voice);
    75         //通知观众观看
    76         this.notifyAll();//通知观看
    77         this.voice = voice;
    78         this.flag = false;
    79     }
    80     //观看
    81     public synchronized void watch() throws InterruptedException {
    82         if(flag){
    83             wait();
    84         }
    85         System.out.println("观众观看了" + voice);
    86         //通知演员表演
    87         this.notifyAll();
    88         this.flag = true;
    89     }
    90 
    91 }

    6: 线程池

     1 package Thread;
     2 
     3 import java.util.concurrent.ExecutorService;
     4 import java.util.concurrent.Executors;
     5 
     6 /**
     7  * author liulei
     8  * data
     9  * since 1.8
    10  * version 1.0
    11  * Description
    12  */
    13 public class Test26 {
    14     public static void main(String[] args) {
    15         //创建服务,创建线程池
    16         ExecutorService service = Executors.newFixedThreadPool(10);
    17         service.execute(new MyThread());//执行
    18         service.execute(new MyThread());
    19         service.execute(new MyThread());
    20         service.execute(new MyThread());
    21         service.shutdown();//关闭链接
    22     }
    23 }
    24 class MyThread implements Runnable{
    25     @Override
    26     public void run() {
    27         for (int i = 0; i < 10; i++) {
    28             System.out.println(Thread.currentThread().getName());
    29         }
    30     }
    31 }

     线程池狂神说的比较简单,推荐自己再多看一些内容

  • 相关阅读:
    Elasticsearch的介绍与安装配置启动问题
    代码发布项目
    gitpython模块
    Paramiko模块
    gojs插件的介绍与使用
    django中如何实现websocket,真正通过websocket实现群聊功能
    如何实现服务端主动给客户端推送消息,websocket详解,以及django如何使用websocket问题
    简单爬取汽车之家新闻(requests模块+bs4)
    http协议版本,响应状态码,正反向代理的区别,与伪静态
    web开发经验——富头像上传编辑器的使用
  • 原文地址:https://www.cnblogs.com/henuliulei/p/12960743.html
Copyright © 2011-2022 走看看