zoukankan      html  css  js  c++  java
  • 黑马程序员---java基础-Java 多线程

     

    进程指的是一个正在执行中的程序,而线程则是进程中一个负责程序执行的控制单元。一个进程中可以有多个执行路径,这就是多线程。开启多个线程可以运行多部分代码,这样就能运行多个功能

    一、多线程的创建

    java中,创建多线程主要有以下两个方式:

    1、继承Thread类:

     1 public class test {
     2 
     3   public static void main(String[] args) {
     4 
     5       //创建对象
     6 
     7       ProducerProject p1=new ProducerProject();
     8 
     9       p1.setName("生产者1");
    10 
    11       ProducerProject p2=new ProducerProject();
    12 
    13       p2.setName("生产者2");
    14 
    15       //开始执行线程
    16 
    17       p1.start();
    18 
    19       p2.start();
    20 
    21   }
    22 
    23 }
    24 
    25 //继承Thread类
    26 
    27 class ProducerProject extends Thread{
    28 
    29   //覆盖Thread类中 的run()方法
    30 
    31   public void run(){
    32 
    33       for(int i=0;i<5;i++){
    34 
    35           System.out.println(Thread.currentThread().getName()+"..生产商品"+i);
    36 
    37       }
    38 
    39   }
    40 
    41 }

    2、实现Runnable接口

     1 public class test2{
     2     public static void main(String[] args){
     3         //创建ProducerProject2对象
     4         ProducerProject2 p=new ProducerProject2();
     5         //将p作为参数构造Thread对象,创建线程
     6         Thread t1=new Thread(p);
     7         Thread t2=new Thread(p);
     8 
     9         t1.setName("生产者1");
    10         t2.setName("生产者1");
    11         //启动线程
    12         t1.start();
    13         t2.start();
    14     }
    15 }
    16 
    17 //实现Runnable接口
    18 class ProducerProject2 implements Runnable{
    19     //实现run()方法
    20     public void run() {
    21         for(int i=0;i<5;i++){
    22             System.out.println(Thread.currentThread().getName()+"..生产商品"+i);
    23         }
    24     }
    25 }

    实现Runnable接口避免了单继承的局限性,并且可以实现资源的共享,适合多个相同的程序代码的线程去处理同一资源,所以一般建议使用第二种线程创建方式。我们可以用静态方法currentThread()来获取当前线程对象,getName()setName()可以用来获取和设置线程名称。

    二、synchronized 锁和waitnotifynotifyAll 应用

     1 /*
     2  * 线程间通信
     3  * 其实是多个线程在操作同一个资源
     4  * 但是操作的动作不同
     5  * 
     6  * 等待 唤醒机制 
     7  * 
     8  * wait()
     9  * nitify()
    10  * notifyAll() 
    11  * 都使用在同步中。
    12  * 因为要对持有监视器(锁)的线程操作
    13  * 所以要使用在同步中,只有同步才具有锁
    14  * 为什么这些操作要定义在Object类中
    15  * 因为这些方法在操作同步线程中,都必须
    16  * 标示他们所操作线程中的锁
    17  * 只有同一个锁上的被等待线程,
    18  * 可以被同一个锁上的notify 唤醒
    19  * 不可以对不同锁上的线程进行唤醒
    20  * 
    21  * 也就是说,等待唤醒的线程必须是同一个锁上
    22  * 而锁可以是任意对象,所以可以被任意对象调用的方法定义在
    23  * Object类
    24  * 
    25  * */
    26 class Res{
    27     String name;
    28     String sex;
    29     boolean rw=false;
    30 }
    31 class Input implements Runnable{
    32     Res res;
    33     public Input(Res res) {
    34         this.res=res;
    35     }
    36     public void run() {
    37         boolean flag=true;
    38         while (true) {
    39             synchronized (res) {
    40                 if(res.rw)
    41                     try {
    42                         res.wait();
    43                     } catch (InterruptedException e) {
    44                         e.printStackTrace();
    45                     }
    46                 if (flag) {
    47                     res.name="mike";
    48                     res.sex="man";
    49                 }else {
    50                     res.name="丽丽";
    51                     res.sex="女";
    52                 }
    53                 flag=flag==true?false:true;
    54                 res.rw=true;
    55                 res.notify();
    56             }
    57         }
    58     }
    59 }
    60 class Output implements Runnable{
    61     Res res;
    62     public Output(Res res) {
    63         this.res=res;
    64     }
    65     public void run() {
    66         while (true) {
    67             synchronized (res) {
    68                 if(!res.rw)
    69                     try {
    70                         res.wait();
    71                     } catch (InterruptedException e) {
    72                         e.printStackTrace();
    73                     }
    74                 System.out.println(res.name+"-"+res.sex);
    75                 res.rw=false;
    76                 res.notify();
    77             }
    78         }
    79     }
    80 }
    81 public class InputOutputDemo {
    82     public static void main(String[] args) {
    83         Res res=new Res();
    84         Input input=new  Input(res);
    85         Output output=new Output(res);
    86         Thread threadIn=new Thread(input);
    87         Thread threadOut=new Thread(output);
    88         threadIn.start();
    89         threadOut.start();
    90     }
    91 
    92 }

    -----------可以对代码进行优化,得到以下代码

     1 /*
     2  * 线程间通信
     3  * 其实是多个线程在操作同一个资源
     4  * 但是操作的动作不同
     5  * 
     6  * 等待 唤醒机制 
     7  * 
     8  * wait()
     9  * nitify()
    10  * notifyAll() 
    11  * 都使用在同步中。
    12  * 因为要对持有监视器(锁)的线程操作
    13  * 所以要使用在同步中,只有同步才具有锁
    14  * 为什么这些操作要定义在Object类中
    15  * 因为这些方法在操作同步线程中,都必须
    16  * 标示他们所操作线程中的锁
    17  * 只有同一个锁上的被等待线程,
    18  * 可以被同一个锁上的notify 唤醒
    19  * 不可以对不同锁上的线程进行唤醒
    20  * 
    21  * 也就是说,等待唤醒的线程必须是同一个锁上
    22  * 而锁可以是任意对象,所以可以被任意对象调用的方法定义在
    23  * Object类中
    24  * 
    25  * ------------------------------代码优化-----------------------------------
    26  * */
    27 class Res2{
    28     private String name;
    29     private String sex;
    30     private boolean rw=false;
    31     public synchronized void setNameSex(String name,String sex) {
    32         if (rw) {
    33             try {
    34                 this.wait();
    35             } catch (InterruptedException e) {
    36                 e.printStackTrace();
    37             }
    38         }
    39         this.name = name;
    40         this.sex = sex;
    41         rw=true;
    42         this.notify();
    43     }
    44     public synchronized void getSexName() {
    45         if (!rw) {
    46             try {
    47                 this.wait();
    48             } catch (InterruptedException e) {
    49                 e.printStackTrace();
    50             }
    51         }
    52         System.out.println(name+"---"+sex);
    53         rw=false;
    54         this.notify();
    55     }
    56 }
    57 class Input2 implements Runnable{
    58     Res2 res;
    59     public Input2(Res2 res) {
    60         this.res=res;
    61     }
    62     public void run() {
    63         boolean flag=true;
    64         while (true) {
    65             
    66                 if (flag) {
    67                     res.setNameSex("mike","man");
    68                 }else {
    69                     res.setNameSex("丽丽","女");
    70                 }
    71                 flag=flag==true?false:true;
    72             }
    73         }
    74 }
    75 class Output2 implements Runnable{
    76     Res2 res;
    77     public Output2(Res2 res) {
    78         this.res=res;
    79     }
    80     public void run() {
    81         while (true) {
    82                 res.getSexName();
    83             }
    84         }
    85 }
    86 public class InputOutputDemo2 {
    87     public static void main(String[] args) {
    88         Res2 res=new Res2();
    89 //        Input2 input=new  Input2(res);
    90 //        Output2 output=new Output2(res);
    91 //        Thread threadIn=new Thread(input);
    92 //        Thread threadOut=new Thread(output);
    93 //        threadIn.start();
    94 //        threadOut.start();
    95         new Thread(new  Input2(res)).start();
    96         new Thread(new Output2(res)).start();
    97         
    98     }
    99 }

    三、用Lock 代替synchronized 实现线程同步

      1 import java.util.concurrent.locks.Condition;
      2 import java.util.concurrent.locks.Lock;
      3 import java.util.concurrent.locks.ReentrantLock;
      4 
      5 /*对于多个生产者和消费者
      6  * 为什么要定义while 判断标记
      7  * 原因:为了让被唤醒的线程再一次判断标记
      8  * 
      9  * 为什么定义notifyAll()
     10  * 因为需要唤醒对方线程
     11  * 因为只用notify ,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待
     12  * 
     13  * 
     14  * jdk 1.5 中国提供了多线程升级解决方案
     15  * 将同步 的synchronized替换成Lock操作
     16  * 将 Object 中的 wait  notify   notifyAll 替换了Condition  对象
     17  * 该对象可以Lock锁进行获取
     18  * 在该例子中,实现了本方只唤醒对方线程操作
     19  * */
     20 public class ProduceConsumeLockDemo {
     21 
     22     public static void main(String[] args) {
     23         Resource2 resource=new Resource2();
     24         Produce2 produce=new Produce2(resource);
     25         Consume2 consume=new Consume2(resource);
     26         
     27         Thread threadPro1=new Thread(produce);
     28         Thread threadPro2=new Thread(produce);
     29         Thread threadConsume2e1=new Thread(consume);
     30         Thread threadConsume2e2=new Thread(consume);
     31         threadPro1.start();
     32         threadPro2.start();
     33         threadConsume2e1.start();
     34         threadConsume2e2.start();
     35     }
     36 
     37 }
     38 class Produce2 implements Runnable{
     39     private Resource2 resource;
     40     public Produce2(Resource2 resource) {
     41         this.resource=resource;
     42     }
     43     public  void run() {
     44         while (true) {
     45             try {
     46                 resource.set("+商品+");
     47             } catch (InterruptedException e) {
     48                 e.printStackTrace();
     49             }
     50         }
     51     }
     52 }
     53 class Consume2 implements Runnable{
     54     private Resource2 resource;
     55     public Consume2(Resource2 resource) {
     56         this.resource=resource;
     57     }
     58     public  void run() {
     59         while (true) {
     60             try {
     61                 resource.out();
     62             } catch (InterruptedException e) {
     63                 e.printStackTrace();
     64             }
     65         }
     66     }
     67     
     68 }
     69 class Resource2{
     70     private String name;
     71     private int count =1;
     72     private boolean flag=false;
     73     //---------------------------------------------------------
     74     private Lock lock =new ReentrantLock();
     75     private Condition con_Produce=lock.newCondition();
     76     private Condition con_Consume=lock.newCondition();
     77     //---------------------------------------------------------
     78     public  void set (String name)throws InterruptedException {
     79         lock.lock();//----------------------- 
     80             try {
     81                 while(flag){ 
     82 //                    con.await();
     83                     con_Produce.await();
     84                 }
     85                 this.name=name+"--"+count++;
     86                 System.out.println(Thread.currentThread().getName()+"--生产者--"+this.name);
     87                 flag=true;
     88 //                con.signal();
     89 //                con.signalAll();//还是唤醒了所有线程
     90                 con_Consume.signal();
     91             }finally{
     92                 lock.unlock();//--------------
     93                 //释放锁的动作一定要执行
     94             }
     95     }
     96     public  void out() throws InterruptedException{
     97         lock.lock();//进来,先拿到锁
     98         try {
     99             while(!flag){
    100                 con_Consume.await();
    101             }
    102             System.out.println(Thread.currentThread().getName()+"----消费者-----"
    103 + this.name);
    104             flag=false;
    105 //con.signal();
    106             con_Produce.signal();
    107         }finally{
    108             lock.unlock();
    109         }
    110         
    111     }
    112 }

    四、Threadstop()方法和interrup()方法

     1 /*
     2  * stop 方法以及过时
     3  * 如何停止线程
     4  * 只有一种方法 run 方法 运行结束
     5  * 
     6  * 开启多线程运行,运行代码通常是循环结构
     7  * 只要控制住循环,就可以让run方法结束,也就是线程结束
     8  * 
     9  * 特殊情况
    10  * 当线程处于冻结状态,就不会读到标记
    11  * 那么线程就不会结束
    12  * 
    13  * interrupt 强制将冻结状态的线程 运行起来  
    14  * 当没有指定的方式让冻结的线程回复都爱运行状态时
    15  * 
    16  * 这时需要对冻结状态进行清除
    17  * 强制让线程恢复到运行状态中来,就可以操作标记你,让线程结束
    18  * Thread类 interrupt 提供了该功能
    19  * 
    20  * 守护线程 或者 用户线程
    21  * 
    22  * 标记为后台线程  :
    23  * 处理结束和普通线程有区别外,其他都一样
    24  * 当所有前台线程都结束后,后台线程自动结束(有依赖的意思)
    25  * 主线程是前台线程。
    26  * 当正在运行的线程都是守护线程是。jvm自动停止
    27  * */
    28 public class StopThreadDemo {
    29     public static void main(String[] args) {
    30         StopThread st=new StopThread();
    31         Thread t1=new Thread(st);
    32         Thread t2=new Thread(st);
    33         t1.setDaemon(true);
    34         t2.setDaemon(true);
    35         t1.start();
    36         t2.start();
    37         
    38         int num=0;
    39         while (true) {
    40             if (num++==60) {
    41 //                st.changFlag();
    42 //                t1.interrupt();
    43 //                t2.interrupt();
    44                 break;
    45             }
    46             System.out.println(Thread.currentThread().getName()+"main -"+num);
    47         }
    48         System.out.println("over");
    49     }
    50 }
    51 class StopThread implements Runnable{
    52     private boolean flag=true;
    53     public synchronized void run() {
    54         while(flag){
    55             try {
    56                 wait();
    57             } catch (InterruptedException e) {
    58 //                e.printStackTrace();
    59                 System.out.println(Thread.currentThread().getName()+"----InterruptedException");
    60                 flag=false;
    61             }
    62             System.out.println(Thread.currentThread().getName()+"----run");
    63         }
    64     }
    65     public void changFlag(){
    66         flag=false;
    67     }
    68 }

    五、Threadjoin()方法

     1 /*
     2  * 当 A线程执行到了 B线程的Join方法时
     3  * A线程就会等待B线程终止,A才会 执行
     4  * join可以用来临时加入线程执行
     5  * 
     6  * Thread[Thread-0,5,main]--- run29
     7 Thread[Thread-1,5,main]--- run32
     8 Thread[Thread-0,5,main]--- run30
     9 Thread【线程名,优先级,线程组】 一般谁开启了线程,线程属于哪个组
    10 优先级 代表 使用cpu 的使用频率
    11 默认优先级是  5
    12 优先级 分 1 ----10 级
    13 static int MAX_PRIORITY     10
    14           线程可以具有的最高优先级。 
    15 static int MIN_PRIORITY     1
    16           线程可以具有的最低优先级。 
    17 static int NORM_PRIORITY    5
    18           分配给线程的默认优先级。 
    19 
    20  * */
    21 public class ClassJoinDemo  {
    22     public static void main(String[] args) throws Exception {
    23         JoinDmeo joinDmeo=new JoinDmeo();
    24         Thread thread1=new Thread(joinDmeo);
    25         Thread thread2=new Thread(joinDmeo);
    26         
    27         thread1.start();
    28 //        thread1.setPriority(Thread.MAX_PRIORITY);
    29         
    30 //        thread1.join();
    31         /*thread1.join();
    32          * thread1 请求执行权
    33          * 主线程处于冻结状态
    34          * thread1 结束后 主线程才恢复到运行状态
    35          * 等待这个线程 终止
    36          * 当进行多线程运行时,
    37          * 临时加入一个线程,让这个线程运算完,
    38          * */
    39         thread2.start();
    40 //        thread1.join();
    41         for (int i = 0; i < 80; i++) {
    42             System.out.println("mian "+i);
    43         }
    44         System.out.println("mina over");
    45     }
    46 
    47 }
    48 class JoinDmeo implements Runnable{
    49     public void run() {
    50         for (int i = 0; i < 70; i++) {
    51             System.out.println(Thread.currentThread().toString()+"--- run"+i);
    52             Thread.yield();//  释放执行权
    53         }
    54     }
    55     
    56 }

     

  • 相关阅读:
    node代码打包为 exe文件---端口进程关闭demo
    java 中几种常用数据结构
    Java 多线程编程
    【java排序】 归并排序算法、堆排序算法
    【java排序】 选择排序,插入排序,希尔算法
    【java排序】冒泡排序、快速排序
    springMVC执行流程及原理
    Java反射机制详解
    【Java并发编程】:并发新特性—信号量Semaphore
    【Java并发编程】:并发新特性—障碍器CyclicBarrier
  • 原文地址:https://www.cnblogs.com/ZkSnug/p/4455463.html
Copyright © 2011-2022 走看看