zoukankan      html  css  js  c++  java
  • 大数据之路week03--day05(线程 I)

    真的,身体这个东西一定要爱护好,难受的时候电脑都不想去碰,尤其是胃和肾。。。

    这两天耽误了太多时间,今天好转了立刻学习,即刻不能耽误!、

    话不多说,说正事:

    1、多线程(理解)

      (1)多线程:一个应用程序有多条执行路径

          进程:正在执行的应用程序

          线程:进程的执行单元,或者说是执行路径

          单线程:一个应用程序只有一条执行路径

          多线程:一个应用程序有多条执行路径

        多进程的意义何在?

          提高CPU的使用率

        多线程的意义何在?

          提高应用程序的使用率

    问题:

      一边玩游戏,一边听歌时同时进行的吗?

        不是,因为单CPU在某一个时间点上只能做一件事。

        而我们在玩游戏,或者听歌的时候,是CPU在做着程序间的高效切换让我们觉得是同时进行的。

      

      (2)Java程序的运行原理及JVM的启动是多线程的吗?

        A:Java命令去启动JVM,JVM会启动一个进程,该进程会启动一个主线程。

        B: JVM的启动是多线程的,因为它最低有两个线程启动了,主线程垃圾回收线程

          两个词汇:并行和并发

            并行是逻辑上同时发生,指在某一个时间段内同时运行多个程序。

            并发是物理上同时发生,指在某一个时间点同时运行多个程序。

          高并发:在某个时间点上很多人去访问一个(大数据)

      (3)多线程的实现方案

        A: 继承Thread类

          步骤:   

            1、自定义类MyThread继承Thread类

            2、MyThread类里面重写run()

            3、创建对象

            4、启动线程

    MyThread类

     1 package com.wyh.Thread01;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午3:04:30
     6 */
     7 public class MyThread extends Thread {
     8     @Override
     9     public void run() {
    10         for(int x = 0; x<500;x++) {
    11             System.out.println(x);
    12         }
    13     }
    14 
    15 }

    测试类:

     1 package com.wyh.Thread01;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午3:05:18
     6 */
     7 public class ThreadDemo01 {
     8     public static void main(String[] args) {
     9         MyThread my1 = new MyThread();
    10         MyThread my2 = new MyThread();
    11         
    12         my1.start();
    13         my2.start();
    14     }
    15     
    16 
    17 }

        B: 实现Runnable接口

            1、自定义类MyThread实现Runnable接口

            2、MyThread类里面重写run()

            3、创建对象

            4、创建Thread对象,把MyThread对象当作参数传入

            5、启动线程

    Runnable类

     1 package com.wyh.Thread04;
     2 
     3 /**
     4  * @author WYH
     5  * @version 2019年11月22日 下午7:00:06
     6  */
     7 public class MyRunnable implements Runnable {
     8 
     9     @Override
    10     public void run() {
    11         for (int x = 1; x <= 500; x++) {
    12             System.out.println(Thread.currentThread().getName() + "--" + x);
    13         }
    14 
    15     }
    16 
    17 }

    测试类:

     1 package com.wyh.Thread04;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午7:01:07
     6 */
     7 public class MyRunnableDemo {
     8     public static void main(String[] args) {
     9         MyRunnable my = new MyRunnable();
    10         Thread t1 = new Thread(my,"王友虎");
    11         Thread t2 = new Thread(my,"赵以浩");
    12         
    13         t1.start();
    14         t2.start();
    15         
    16     }
    17 
    18 }

      (4)线程的调度和优先级问题

        A:线程的调度

          a:分时调度

          b:抢占式调度(Java采用的是该调度方式)

        B:获取和设置线程的优先级

          a:默认是5

          b:范围是1-10

      (5)线程的控制(常见方法)

        A:休眠线程(测试类在这不写,基本不变)

     1 package com.wyh.Thread03;
     2 
     3 import java.util.Date;
     4 
     5 /** 
     6 * @author WYH
     7 * @version 2019年11月22日 下午3:04:30
     8 */
     9 public class ThreadSleep extends Thread {
    10     public ThreadSleep() {
    11         super();
    12         // TODO Auto-generated constructor stub
    13     }
    14 
    15     public ThreadSleep(String name) {
    16         super(name);
    17         // TODO Auto-generated constructor stub
    18     }
    19 
    20     @Override
    21     public void run() {
    22         for(int x = 0; x<500;x++) {
    23             System.out.println(getName()+x+" 日期:"+new Date());
    24             //睡眠1秒
    25             try {
    26                 Thread.sleep(1000);
    27             } catch (InterruptedException e) {
    28                 // TODO Auto-generated catch block
    29                 e.printStackTrace();
    30             }
    31             
    32         }
    33     }
    34 
    35 }

        B:加入线程(run方法类不变)

     1 package com.wyh.Thread03;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午3:05:18
     6 * 
     7 * join 为了让某些线程执行完毕,才能执行其他的(线程加入)
     8 * 
     9 * 
    10 * 
    11 */
    12 public class ThreadJoinDemo {
    13     public static void main(String[] args) {
    14         
    15         ThreadPriority my1 = new ThreadPriority("王友虎");
    16         ThreadPriority my2 = new ThreadPriority("李宏灿");
    17         ThreadPriority my3 = new ThreadPriority("齐博源");
    18         
    19         my1.start();
    20         try {
    21             my1.join();
    22         } catch (InterruptedException e) {
    23             // TODO Auto-generated catch block
    24             e.printStackTrace();
    25         }
    26         
    27         my2.start();
    28         my3.start();
    29         
    30     }
    31     
    32 
    33 }

        C:礼让线程(省略测试类代码)

     1 package com.wyh.Thread03;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午4:28:15
     6 */
     7 public class ThreadYield extends Thread {
     8     public ThreadYield() {
     9         super();
    10         // TODO Auto-generated constructor stub
    11     }
    12 
    13     public ThreadYield(String name) {
    14         super(name);
    15         // TODO Auto-generated constructor stub
    16     }
    17 
    18     @Override
    19     public void run() {
    20         for(int x = 0; x<200;x++) {
    21             System.out.println(getName()+x);
    22             Thread.yield();
    23         }
    24     }
    25 }

        D:后台线程(省略继承类的代码)//注意!!!!必须在启动前声明

     1 package com.wyh.Thread03;
     2 
     3 /**
     4  * @author WYH
     5  * @version 2019年11月22日 下午4:42:16
     6  * 
     7  * 守护线程
     8  * 
     9  * 理解:坦克大战,黄绿坦克守护家,家没了,坦克也没了
    10  * 
    11  */
    12 public class ThreadDeamonDemo {
    13     public static void main(String[] args) {
    14         ThreadDeamon td1 = new ThreadDeamon("关羽");
    15         ThreadDeamon td2 = new ThreadDeamon("张飞");
    16         
    17         
    18         //注意!!!!必须在启动前声明
    19         td1.setDaemon(true);
    20         td2.setDaemon(true);
    21 
    22         td1.start();
    23         td2.start();
    24 
    25         
    26         
    27         
    28         Thread.currentThread().setName("刘备");
    29         for (int x = 0; x < 5; x++) {
    30             System.out.println(Thread.currentThread().getName() + x);
    31         }
    32     }
    33 
    34 }

        E:终止线程(不推荐使用stop,而且该方法已经过时,推荐使用interrupt)

    继承类:

     1 package com.wyh.Thread03;
     2 
     3 import java.util.Date;
     4 
     5 /** 
     6 * @author WYH
     7 * @version 2019年11月22日 下午4:57:38
     8 */
     9 public class ThreadStop extends Thread{
    10     @Override
    11     public void run() {
    12         System.out.println("时间:"+new Date());
    13         
    14         //睡眠10秒钟
    15         try {
    16             Thread.sleep(10000);
    17         } catch (InterruptedException e) {
    18             System.err.println("睡眠被意外中止!!");
    19         }
    20         
    21         System.out.println("时间:"+new Date());
    22         
    23     }
    24 }

    测试类:

     1 package com.wyh.Thread03;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午5:00:21
     6 */
     7 public class ThreadStopDemo {
     8     public static void main(String[] args) {
     9         ThreadStop ts = new ThreadStop();
    10         ts.start();
    11         
    12         try {
    13             Thread.sleep(3000);
    14 //            ts.stop();  //不建议使用  因为后面的代码无法执行
    15             ts.interrupt();
    16         } catch (InterruptedException e) {
    17             e.printStackTrace();
    18         }
    19         
    20         
    21     }
    22 
    23 }

      (6)线程的生命周期(图解)

      (7)电影院卖票程序的实现

          A:继承Thread类

    继承类:

     1 package com.wyh.Thread05;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午7:33:38
     6 */
     7 public class SellTicket extends Thread {
     8     private static int tickets = 100;
     9     
    10     @Override
    11     public void run() {
    12         while(true) {
    13             if(tickets>0) {
    14                 System.out.println(getName()+"窗口正在售卖第"+(tickets--)+"张票。。");
    15             }
    16             
    17         }
    18     }
    19 }

    测试类:

     1 package com.wyh.Thread05;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午7:36:19
     6 */
     7 public class TicketDemo {
     8     public static void main(String[] args) {
     9         //先创建多个线程
    10         SellTicket st1 = new SellTicket();
    11         SellTicket st2 = new SellTicket();
    12         SellTicket st3 = new SellTicket();
    13         
    14         //给多个线程起名字’
    15         st1.setName("窗口1");
    16         st2.setName("窗口2");
    17         st3.setName("窗口3");
    18         
    19         st1.start();
    20         st2.start();
    21         st3.start();
    22         
    23         
    24         
    25     }
    26 
    27 }

          B:实现Runnable接口

    实现Runnable接口类:

     1 package com.wyh.Thread05;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午7:42:37
     6 */
     7 public class SellTicket_Runnable implements Runnable {
     8     private int tickets = 100;
     9 
    10     @Override
    11     public void run() {
    12         while(true) {
    13             if(tickets>0) {
    14                 System.out.println(Thread.currentThread().getName()+"窗口正在售卖第"+(tickets--)+"张票。。");
    15             }
    16         }
    17 
    18     }
    19 
    20 }

    测试类:

     1 package com.wyh.Thread05;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午7:43:48
     6 */
     7 public class SellTicket_RunnableDemo {
     8     public static void main(String[] args) {
     9         SellTicket_Runnable sr = new SellTicket_Runnable();
    10         
    11         Thread t1 = new Thread(sr,"窗口1");
    12         Thread t2 = new Thread(sr,"窗口2");
    13         Thread t3 = new Thread(sr,"窗口3");
    14         
    15         t1.start();
    16         t2.start();
    17         t3.start();
    18         
    19     }
    20 
    21 }

      (8)电影院卖票程序出的问题

        A:为了更加符合真实场景,加入了休眠100毫秒。

        B:买票问题

          a:同票被多次出售

          b:出现0票和负数票

      (9)多线程安全问题的原因(也是我们以后判断一个程序是否有安全问题的依据)

        A:是否有多线程环境

        B:是否有共享数据

        C:是否有多条语句操作共享数据

      (10)同步解决线程安全问题(以解决上面售票的为例解决)

        A:同步代码块

            synchronized(对象){

              需要被同步的代码;

            }

          这里的对象可以是任意对象(充当锁的作用,下面也是相同作用)

    实现接口类:(测试类代码不变)

     1 package com.wyh.Thread06_tickets;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午7:42:37
     6 */
     7 public class SellTicket_Runnable implements Runnable {
     8     private int tickets = 300;
     9     private Object obj = new Object();  //如同一把锁 多个线程共用一把锁,把对共享数据的操作包起来
    10 
    11     @Override
    12     public void run() {
    13         while(true) {
    14             synchronized(obj) {
    15                 if(tickets>0) {
    16                     try {
    17                         Thread.sleep(30);
    18                     } catch (InterruptedException e) {
    19                         // TODO Auto-generated catch block
    20                         e.printStackTrace();
    21                     }
    22                     System.out.println(Thread.currentThread().getName()+"窗口正在售卖第"+(tickets--)+"张票。。");
    23                 }
    24             }
    25             
    26         }
    27 
    28     }
    29 
    30 }

        B:同步方法

          把同步放在方法上。

          这里的锁对象是 this

    实现接口类:(测试类代码不变)

     1 package com.wyh.Thread07_tickets2_同步方法静态;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午7:42:37
     6 */
     7 public class SellTicket_Runnable implements Runnable {
     8     private int tickets = 300;
     9     private int x = 0;
    10     
    11     //用obj对象做锁
    12     private Object obj = new Object();  //如同一把锁 多个线程共用一把锁,把对共享数据的操作包起来
    13     
    14 
    15     @Override
    16     public void run() {
    17         if(x%2==0) {
    18             while(true) {
    19                 synchronized(this) {
    20                     if(tickets>0) {
    21                         try {
    22                             Thread.sleep(30);
    23                         } catch (InterruptedException e) {
    24                             // TODO Auto-generated catch block
    25                             e.printStackTrace();
    26                         }
    27                         System.out.println(Thread.currentThread().getName()+"窗口正在售卖第"+(tickets--)+"张票。。");
    28                     }
    29                 }
    30                 
    31             }
    32         }else {
    33                 synchronize();
    34         }
    35         
    36 
    37     }
    38 
    39 
    40     private synchronized void synchronize() {
    41         while(true) {
    42                 if(tickets>0) {
    43                     try {
    44                         Thread.sleep(30);
    45                     } catch (InterruptedException e) {
    46                         // TODO Auto-generated catch block
    47                         e.printStackTrace();
    48                     }
    49                     System.out.println(Thread.currentThread().getName()+"窗口正在售卖第"+(tickets--)+"张票。。");
    50                 }
    51             
    52         }
    53         
    54     }
    55 }

        C:静态同步方法

           把同步加在方法上。

           这里的锁对象是当前类的字节码文件对象(反射)

     1 package com.wyh.Thread07_tickets2_同步方法静态;
     2 
     3 /** 
     4 * @author WYH
     5 * @version 2019年11月22日 下午7:42:37
     6 */
     7 public class SellTicket_Runnable2 implements Runnable {
     8     private static int tickets = 300;
     9     private int x = 0;
    10     
    11     
    12 
    13     @Override
    14     public void run() {
    15         if(x%2==0) {
    16             while(true) {
    17                 synchronized(SellTicket_Runnable2.class) {
    18                     if(tickets>0) {
    19                         try {
    20                             Thread.sleep(30);
    21                         } catch (InterruptedException e) {
    22                             e.printStackTrace();
    23                         }
    24                         System.out.println(Thread.currentThread().getName()+"窗口正在售卖第"+(tickets--)+"张票。。");
    25                     }
    26                 }
    27                 
    28             }
    29         }else {
    30                 synchronize();
    31         }
    32         
    33 
    34     }
    35 
    36 
    37     private synchronized static void synchronize() {
    38         while(true) {
    39                 if(tickets>0) {
    40                     try {
    41                         Thread.sleep(30);
    42                     } catch (InterruptedException e) {
    43                         e.printStackTrace();
    44                     }
    45                     System.out.println(Thread.currentThread().getName()+"窗口正在售卖第"+(tickets--)+"张票。。");
    46                 }
    47             
    48         }
    49         
    50     }
    51 }

    ·  (11)回顾以前的线程安全的类

          A:StringBuffer

          B:Vector

          C:HashTable

          D:如何把一个线程不安全的集合变成一个线程安全的集合类

              用Collections 工具类的方法即可。

    以List集合为例:其他集合创建方法类似,具体看API

     1 package Collections保证线程安全的;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Collections;
     5 import java.util.List;
     6 
     7 /** 
     8 * @author WYH
     9 * @version 2019年11月22日 下午9:10:58
    10 */
    11 public class Demo {
    12     public static void main(String[] args) {
    13         //以List集合为例
    14         //以前的我们是这么做的
    15         List<String> list1 = new ArrayList<String>(); //这么创建的List是不安全的
    16         
    17         
    18         
    19         //Collections 工具类提供的方法 同步安全的
    20         List<String> list2 = Collections.synchronizedList(new ArrayList<String>());
    21         
    22         list2.add("1");
    23         list2.add("2");
    24         
    25         for(String s : list2) {
    26             System.out.println(s);
    27         }
    28     }
    29 
    30 }

    线程中需要注意的问题:

      1、Thread中start()方法的功能就是创建一个新的线程,并自动调用该线程的run()方法,直接调用run()方法是不会创建一个新的线程的,直接调用相当于调用一个普通方法。

      2、执行一个线程实际就是执行该线程run方法中的代码

      3、一个Thread对象只能代表一个线程。

          一个Thread对象不能调用两次start()方法,否则会抛出java.lang.IllegalThreadStateException异常

  • 相关阅读:
    【BZOJ】2209: [Jsoi2011]括号序列(splay)
    【BZOJ】1251: 序列终结者(splay)
    【UOJ】【UR #2】猪猪侠再战括号序列(splay/贪心)
    【BZOJ】3781: 小B的询问(莫队算法)
    【BZOJ】3289: Mato的文件管理(莫队算法+树状数组)
    【BZOJ】2038: [2009国家集训队]小Z的袜子(hose)(组合计数+概率+莫队算法+分块)
    【SPOJ】7258. Lexicographical Substring Search(后缀自动机)
    vue 中 event.stopPropagation() 和event.preventDefault() 使用
    Vue 中 使用v-show
    Vue v-if以及 v-else 的使用
  • 原文地址:https://www.cnblogs.com/wyh-study/p/11914742.html
Copyright © 2011-2022 走看看