zoukankan      html  css  js  c++  java
  • java学习-线程

    由于自己最近接手一个项目,构思过程中,线程可能会用的较多,所以今天翻出来把线程这块好好复习一下,以下是一点学习总结。分享写的比较拙略,只为自己笔记。为自己以后存储参考资源而已。
      pass:(被重写的方法不能跑一个比父类更大的异常)

    创建于一个继承thread的子类:

     1 class testThread extends Thread{
     2     public void Run(){//新建一个线程里的run方法,实现此子线程需要完成的功能
     3         for(int i = 0;i < 100;i++){
     4             Thread.currentThread().sleep(1000);
     5             System.out.println(Thread.currentThread().getName()+":"+i);
     6         }
     7     }
     8 }
     9 public class TestThread{
    10    static void main(String arg[]){
    11       testThread sT1 = new testThread();
    12       testThread sT2 = new testThread();//创建一个子类的对象
    13       sT1.setName("线程1:");
    14       sT1.setpriority(Thread.MAX.PRIORITY);
    15       sT1.start();
    16       sT2.setName("线程2:");
    17       sT2.start();
    18       //调用线程的start方法,启动此线程,调用相应的run方法,
    19       //一个线程只能执行一次start,具体请见jdk手册。
    20       //如果此处启用的是run方法,则不是双线程。必须是start方法。
    21    Thread.currentThread().setName("子线程:");
    22     for(int i = 0;i < 100;i++){
    23         System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getPriority()+":"i);
    24         /*if(i % 10 == 0){
    25             Thread.currentThread().yield();
    26             
    27         }*/
    28         /*if(i % 10 ==0){
    29             try{
    30                 sT1.join();
    31             }catch(InterruptedException e){
    32                e.printStackTrace();
    33             }
    34         }*/
    35         }
    36         System.out.println(sT1.isAlive());/*返回FALSE*/
    37    }
    38 }

    Thread常用方法:
    1.start() 启动线程并执行相应的run方法。
    2.run()  子线程要执行的代码放入其中,一般都是被重写。
    3.currentThread() 静态的,调取当前的线程
    4.getName() 获取当前线程的名字
    5.setName() 设置子线程的名字
    6.yield()  线程释放当前cpu的执行权
    7.join() 在a线程中调用b线程的join方法,表示,当执行到此方法,a线程停止,直至b线程全部结束,a线程才继续执行
    8.isAlive() 判断当前线程是否还存活
    9.sleep(long l) 显示的当前线程睡眠1毫秒
    10.设置线程的优先级:getpriority() 返回线程优先级;setpriority(int newpriority)改变线程的优先级

     1 /*
     2   创建两个子线程,让其中一个输出1-100之间的偶数,另一个输出1-100之间的奇数
     3 */
     4 class SubThread1 extends Thread{
     5     public void Run(){
     6         for (int i = 1; i < 100;i++){
     7             if(i % 2 == 0){
     8                 System.out.println(Thread.currentThread().getName()+":"+i);
     9             }
    10         }
    11     }
    12 }
    13 class SubThread2 extends Thread{
    14     public void Run(){
    15         for (int i = 1; i < 100;i++){
    16             if(i % 2 != 0){
    17                 System.out.println(Thread.currentThread().getName()+":"+i);
    18             }
    19         }
    20     }
    21 }
    22     public class TestThread{
    23             public static void main(String[] args) {
    24                  SubThread sT1 = new SubThread1();
    25                   SubThread sT2 = new SubThread();
    26                   //sT1.start();
    27                   //sT2.start();
    28                   //继承于Thread类的匿名对象
    29                   new Thread(){
    30                     public void Run(){
    31                      for (int i = 1; i < 100;i++){
    32                        if(i % 2 != 0){
    33                          System.out.println(Thread.currentThread().getName()+":"+i);
    34             }
    35         }
    36     }}.start();
    37                  new Thread(){
    38                     public void Run(){
    39                      for (int i = 1; i < 100;i++){
    40                        if(i % 2 != 0){
    41                          System.out.println(Thread.currentThread().getName()+":"+i);
    42             }
    43         }
    44     }}.start();
    45 
    46             }
    47     }
     1 /*模拟火车站首售票窗口,开启三个窗口售票.总票数为100张*/
     2  class Window extends Thread{
     3         static int tickets = 100;//声明为固定变量实现公用,限制只有一百张,但声明周期很长
     4          public void Run(){
     5              while(true){
     6                  if(tickets > 0){
     7                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--);
     8                  }else{
     9                      break;//退出
    10                  }
    11              }
    12          }
    13  }
    14  public class TestWindow{
    15 
    16  }
    17 
    18  public static void main(String[] args) {
    19      Window W1 = new Window();
    20      Window W2 = new Window();
    21      Window W3 = new Window();
    22 
    23      W1.setName("窗口1:");
    24      W2.setName("窗口2:");
    25      W3.setName("窗口3:");
    26 
    27      W1.start();
    28      W2.start();
    29      w3.start();
    30  }

    第二种方式-实现:

    //1.创建一个实现了runable的类 
    class PrintNum1 implements Runable{
        public void run(){//实现接口的抽象方法
             for (int i = 1; i < 100;i++){
                           if(i % 2 != 0){
                             System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
        }
    }
    public class TestWindow1{
        public static void main(String[] args) {
            //2.创建一个runable接口的实现对象
            PrintNum1 p = new PrintNum1();
            //要想启动一个多线程,必须调用start方法
            //3.将此对象作为形参传递给Thread类的构造器中,创建Thread类的对象,此对象即为一个线程。
            Thread T1 = new Thread(p);//构造一个Thread对象
            T1.start();
             //启动线程,执行Thread对象生成时构造器形参的对象的Run方法
    
            //4.在创建一个线程
            Thread T2 = new Thread(p);//构造一个Thread对象
            T2.start();
        }
     }

    实现的方式实现多窗口售票 存在线程的安全问题
    为何会出现程序的安全问题?
    由于一个线程在操作共享数据的执行过程中未执行完的情况下,另外的线程参与进来,导致共享数据存在安全问题
    如何解决?
    必须让一个操作共享数据完毕之后,其他线程才有机会共享数据的操作。
    java如何实现线程安全?
    线程的同步:1.同步代码块 synchronized(同步监视器){
        需要同步的代码块(操作数据共享的代码)
    }
    共享数据:多个线程共同操作的一个数据
    同步监视器:由任何一个类的对象来充当,那个线程获取此监视器,谁就执行大括号里面的代码 俗称:锁
    在实现的方式中考虑同步的话可以考虑this来充当锁,但在继承当中需要慎重.

     1 class Window1 implements Thread{
     2     int ticket = 100;//共享数据
     3     static Object object = new Object();
     4     public void run(){
     5         //Object object = new Object();不能在此处写,这样会导致引发三次局部变量
     6         while(true){
     7             synchronized(object){//此处可以为this,代表当前的对象W1
     8                  if(tickets > 0){
     9                      try{//这个地方会出现重票和错票
    10 
    11                         Thread.currentThread().sleep(10);//让其休眠10毫秒
    12                      }catch(InterruptedException e){
    13                        e.printStackTrace();
    14                      }
    15                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--);
    16                  }else{
    17                      break;//退出
    18              }
    19          }
    20           }
    21     }
    22 }
    23 public class TestWindow1{
    24   public static void main(String[] args) {
    25       Window1 W1 = new Window1();
    26       Thread t1 = new Thread(W1);
    27       Thread t2 = new Thread(W1);
    28     /*只new了一个w对象,三个线程共享*/
    29       t1.setName("窗口1:");
    30      t2.setName("窗口2:");
    31      
    32       t1.start();
    33   //共享同一个W对像
    34       
    35       t2.start();
    36 
    37   }
    38 
    39 }
     1 /*实现改进版售票器*/
     2 class Window1 implements Thread{
     3     int ticket = 100;
     4     public void run(){
     5         while(true){
     6                  if(tickets > 0){
     7                      /*try{//这个地方会出现重票和错票
     8    
     9                         Thread.currentThread().sleep(10);//让其休眠10毫秒
    10                      }catch(InterruptedException e){
    11                        e.printStackTrace();
    12                      }*/
    13                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--);
    14                  }else{
    15                      break;//退出
    16              }
    17           }
    18     }
    19 }
    20 public class TestWindow1{
    21   public static void main(String[] args) {
    22       Window1 W1 = new Window1();
    23       Thread t1 = new Thread(W1);
    24       Thread t2 = new Thread(W1);
    25     /*只new了一个w对象,三个线程共享*/
    26       t1.setName("窗口1:");
    27      t2.setName("窗口2:");
    28      
    29       t1.start();
    30   //共享同一个W对像
    31       
    32       t2.start();
    33 
    34   }

    同步方法
    将操作共享数据的方法声明为synchronized,
    即此方法为同步方法,能够保证当其中一个线程执行此方法时,
    其他线程在外等待直到此线程执行完此方法
    >同步方法的锁是当前对象:this
    线程的弊端:同一个时间只有一个线程访问共享数据,效率变低了。

     1 /*实现改进版售票器*/
     2 class Window1 implements Thread{
     3     int ticket = 100;
     4     public void run(){
     5         while(true){
     6         show();
     7 
     8         }
     9     }
    10     public synchronized void show(){
    11     
    12                  if(tickets > 0){
    13                      try{//这个地方会出现重票和错票
    14                         Thread.currentThread().sleep(10);//让其休眠10毫秒
    15                      }catch(InterruptedException e){
    16                        e.printStackTrace();
    17                      }
    18                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--);
    19                  }else{
    20                      break;//退出
    21              
    22           }
    23     }
    24 }
    25 public class TestWindow1{
    26   public static void main(String[] args) {
    27       Window1 W1 = new Window1();
    28       Thread t1 = new Thread(W1);
    29       Thread t2 = new Thread(W1);
    30     /*只new了一个w对象,三个线程共享*/
    31       t1.setName("窗口1:");
    32      t2.setName("窗口2:");
    33      
    34       t1.start();
    35   //共享同一个W对像
    36       
    37       t2.start();
    38 
    39   }
     1 /*继承实现同步方法*/
     2 class Window extends Thread{
     3         static int tickets = 100;//声明为固定变量实现公用,限制只有一百张,但声明周期很长
     4         static Object o = new Object();
     5          public void Run(){
     6              while(true){
     7                  synchronized(o){
     8                  if(tickets > 0){
     9                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--);
    10                  }else{
    11                      break;//退出
    12                  }
    13                }
    14              }
    15          }
    16  }
    17  public class TestWindow{
    18  public static void main(String[] args) {
    19      Window W1 = new Window();
    20      Window W2 = new Window();
    21      Window W3 = new Window();
    22 
    23      W1.setName("窗口1:");
    24      W2.setName("窗口2:");
    25      W3.setName("窗口3:");
    26 
    27      W1.start();
    28      W2.start();
    29      w3.start();
    30  }
    31 }
    /*懒汉模式-单例模式
    sleep()和yield()不会释放锁的,
    static方法里面锁不能写this,使用当前类本身充当*/
    class  Singleton{
       private Singleton(){
    
       }
       private static Singleton instance = null;
       public static Singleton getInstance(){
           if(instance == null){
           synchronized(Singleton.class){
           if(instance == null){
               instance = new Singleton();
           }
           }
           }
           return instance;
       }
     }
    
    
     public class TestSingleton{
      public static void main(String[] args) {
          Singleton s1 = new Singleton.getInstance();
          Singleton s2 = new Singleton.getInstance();
    
          System.out.println(s1 == s2);//判断两个对象相等,只能用==
      }
     }
     1 /*银行存钱问题
     2 */
     3 class Count{
     4     double balance;//余额
     5     public Account(){
     6 
     7     }    
     8     public synchronized void despoit(double amt){//存钱
     9       notify();//实现二者交替打印
    10       balance += amt;
    11       try{
    12           Thread.currentThread().sleep(10);
    13       }
    14       catch(InterruptedException e){
    15             e.printStackTrace();
    16       }
    17       System.out.println(Thread.currentThread().getName()+":"+balance);
    18       wait();
    19     }
    20 
    21 }
    22 class Customer extends Thread{
    23     Account account;
    24     public Customer(Account account){
    25         this.account = account;
    26     }
    27     public void run(){
    28        for(int i = 0;i<3;i++){
    29            account.despoit(1000);
    30        }
    31     }
    32 }
    33 public class TestAccount{
    34    public static void main(String[] args) {
    35        Account acct =new Account();
    36        Customer c1 = new Customer(acct);
    37        Customer c2 = new Customer(acct);
    38        Customer c3 = new Customer(acct);
    39 
    40        c1.setName("1");
    41        c2.setName("2");
    42        c3.setName("3");
    43 
    44        c1.start();
    45        c2.start();
    46        c3.start();
    47    }
    48 }
     1 /*死锁问题--处理线程同步时容易出现
     2 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的资源,就形成了线程的死锁*/
     3  public class TestDeadLock{
     4      static StringBuffer sb1 = new StringBuffer();
     5      static StringBuffer sb2 = new StringBuffer();
     6 
     7      public static void main(String[] args) {
     8          new Thread(){
     9               public void run(){
    10                synchronized(sb1){
    11                 try{
    12                     Thread.currentThread().sleep(10);
    13                   }
    14                    catch(InterruptedException e){
    15                      e.printStackTrace();
    16                   }
    17                 sb1.append("A");
    18                   synchronized(sb2){
    19                     sb2.append("B");
    20                      System.out.println(sb1);
    21                      System.out.println(sb2);
    22                    }
    23                 }
    24               }
    25          }.start();
    26 
    27          new Thread(){
    28              public void run(){
    29                synchronized(sb1){
    30                    try{
    31                     Thread.currentThread().sleep(10);
    32                   }
    33                    catch(InterruptedException e){
    34                      e.printStackTrace();
    35                   }
    36                 sb1.append("C");
    37                   synchronized(sb2){
    38                     sb2.append("D");
    39                     System.out.println(sb1);
    40                      System.out.println(sb2);
    41                    }
    42                 }
    43              }
    44          }.start();
    45      }
    46  } 
    /*Deadlock.java*/
    class A{
        public synchronized void foo(B b){
            System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入了A实例的foo方法");
            try{
                Thread.sleep(200)
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用b的last方法");
        }
        public synchronized void Last(){
            System.out.println("进入了A的last方发出内部");
        }
    }
    
    class B{
       public synchronized void bar(A a){
         System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入了B实例的bar方法");try{
                Thread.sleep(200)
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用A的last方法");
        }
        public synchronized void Last(){
            System.out.println("进入了B的last方发出内部");
        }
    }
    public class Deadlock implements Runable{
        A a = new A();
        B b = new B();
    
        public void init(){
            Thread.currentThread.setName("主线程");
            //调用a对象的foo方法
            a.foo(b);
            System.out.println("进入了主线程之后");
        }
        public void run(){
            Thread.currentThread.setName("副线程");
           //调用b对象的bar方法
            b.bar(a);
            System.out.println("进入了副线程之后");
        }
        public static void main(String[] args) {
            Deadlock d1 = new Deadlock();
            new Thread(d1).start();//启动run方法
            d1.init();
        }
    }

    线程通信
    1.wait()方法:令当前线程挂起并放弃CPU,同步资源,使别的线程可访问并修改资源,而当前线程排队等候再次对资源的访问
    2.notify()方法:唤醒正在排队等待同步资源的线程中优先级最高的
    3.notifyAll()方法:唤醒正在等待资源的所有线程结束等待
    java.lang.Object提供的这三个方法只有在synchronized方法中或synchronized代码块中才能使用,否则会报错
    线程通信:

     1 打印1-100,线程1,线程2交替打印*/
     2 class PrintNum implements Runable{
     3     int num = 1;
     4        public void run(){
     5            
     6            while(true){
     7             synchronized(this){
     8                 notify();
     9                if(num<100){
    10                    try{Thread.currentThread().sleep(10);
    11                    }catch(InterruptedException e){
    12                      e.printStackTrace();
    13                    }
    14                    System.out.println(Thread.currentThread().getName()+":"+num);
    15                    num++;
    16                }else{
    17                    break;
    18              }
    19              wait();
    20          }
    21            }
    22        }
    23 }
    24 
    25 public class TestCommunication{
    26     public static void main(String[] args) {
    27         PrintNum p = new PrintNum();
    28         Thread t1 = new Thread(p);
    29         Thread t2 = new Thread(p);
    30 
    31         t1.setName("甲");
    32         t1.setName("乙");
    33 
    34         t1.start();
    35         t2.start();
    36     }
    37 
    38 }

    生产者、消费者问题
    多线程:消费者/生产者
    共享数据:产品数量


     1 class Clerk{//店员
     2     int product;
     3 
     4     public synchronized void addProduct(){//生产产品
     5         if(product >= 20){
     6             wait();
     7         }else{
     8             product++;
     9             System.out.println(Thread.currentThread().getName()+":生产了第"+ product +"个");
    10             notifyall();
    11         }
    12 
    13     }
    14     public synchronized void consumeProduct(){//消费产品
    15         if(product <= 0){
    16             wait();
    17         }else{
    18             System.out.println(Thread.currentThread().getName()+"消费了第"+product +"个");
    19             product--;
    20             notifyall();
    21         }
    22     }
    23 }
    24 class Producer implements Thread{//生产者
    25     Clerk clerk;
    26 
    27     public Producer(Clerk clerk){
    28         this.clerk = clerk;
    29     }
    30     public void run(){
    31         System.out.println("生产者开始生产产品。");
    32         while(true){
    33             try{ 
    34                 Thread.currentThread().sleep(10);
    35                    }catch(InterruptedException e)
    36                    {
    37                      e.printStackTrace();
    38                    }
    39             clerk.addProduct();
    40         }
    41     }
    42 
    43 }
    44 class Consumer implements Runable{//消费者
    45      Clerk clerk;
    46      public Consumer(Clerk clerk){
    47          this.clerk = clerk;
    48      }
    49      public void run(){
    50          System.out.println("消费者开始消费产品。");
    51          while(true){
    52             try{
    53                 Thread.currentThread().sleep(10);
    54                    }catch(InterruptedException e) 
    55                    {
    56                      e.printStackTrace();
    57                    }
    58              clerk.consumeProduct();
    59          }
    60      }
    61 }
  • 相关阅读:
    Mac使用nginx+rtmp服务器
    iOS开发必不可少的76个工具
    AVPlayer缓存实现
    视频直播分析
    github部分有意思的库记录
    iOS四种多线程(swift和oc)
    Java的static关键字浅析
    JavaScript获取屏幕参数
    JavaScript中XMLHttpRequest实现跨域访问
    【CenchaTouch 学习笔记】Controller
  • 原文地址:https://www.cnblogs.com/Terminaling/p/4072359.html
Copyright © 2011-2022 走看看