当前位置:必发365电子游戏 > 操作系统 > 必发365手机版     2.多线程执行的特点
必发365手机版     2.多线程执行的特点
2019-12-19

一.多线程
     1.基本概念
         进度:正在运行中的程序,一个经过中足足含有一个线程
         线程:进度的任务,执行义务的一个坦途,贰个历程中得以分包几个线程
     2.八线程实施的特点:
         两种办法:分时调节/抢占式调节(java归属侵吞卡塔尔(英语:State of Qatar)
二.Thread 类(java.lang)
     1.概述:使用该类表示四线程对象,只要创立一个Thread对象,正是三个线程对象发生了
     2.定义:public class Thread extends Object implements Runnable
     3.构造方法:
         Thread(卡塔尔:无参布局,分配新的 Thread 对象
         Thread(String name卡塔尔(英语:State of Qatar):使用钦赐的称号分配新的 Thread 对象,设置线程名称
         Thread(Runnable target卡塔尔(قطر‎:选拔Runnable接口子类对象,实例化Thread对象
         Thread(Runnable target, String name卡塔尔(英语:State of Qatar):选择Runnable接口子类对象,实例化Thread对象,并设置线程名称
     4.静态办法:
         public static Thread currentThread(卡塔尔国{}:重返这段日子正在执行的线程 [线程名,优先级,]
         public static void sleep(long millis卡塔尔(قطر‎ throws InterruptedException{}:使这段日子线程休眠多少阿秒
         public static void yield(卡塔尔(英语:State of Qatar){}:将日前实施的线程暂停,允许其余线程施行
    
     5.常用艺术:
         public void run(卡塔尔(英语:State of Qatar){}:假诺该线程是接纳独立的 Runnable 运维目的协会的,则调用该 Runnable 对象的 run
                             方法;不然,该方法不进行此外操作并赶回。<所以该办法应自觉重写!!!>
         public void start(卡塔尔{}:使该线程开头实行;Java 设想机调用该线程的 run 方法
         public final String getName(卡塔尔(قطر‎{}:再次来到线程的称号
         public final int getPriority(卡塔尔国{}:重返线程优先级
         public final void setName(String name卡塔尔(قطر‎{}:设定线程名称
         public final void setPriority(int newPriority卡塔尔(قطر‎{}:设定线程的预先值
         public final ThreadGroup getThreadGroup(){}:Returns the thread group to which this thread belongs.
                                             This method returns null if this thread has died (been stopped).
     代码演示:        

进程

  1  //多线程基本练习-Thread类
  2         class MyThread extends Thread{
  3              //重写run()
  4              @Override
  5              public void run(){
  6                  for(int i = 0; i < 100; i++){
  7                      System.out.println(Thread.currentThread()+"Jack"+i);
  8                  }
  9              }
 10          }
 11 
 12          public class ThreadDemo{
 13              public static void main(String[] args){
 14                  //创建一个线程
 15                 MyThread my = new MyThread();
 16                  //启动线程
 17                 my.start();
 18 
 19                  //主线程执行如下任务
 20                 for(int i = 0; i<100; i++){
 21                      System.out.println(Thread.currentThread()+"肉丝"+i);
 22                  }
 23 
 24                  //返回当前运行的线程名称
 25                 String s = my.getName();
 26                  System.out.println("当前线程名称为:"+s);//Thread-0
 27 
 28                  //修改线程名称
 29                 my.setName("Smith--");
 30                  System.out.println("修改后-当前线程名称为:"+my.getName());
 31 
 32                  //返回线程优先级
 33                 int i = my.getPriority();
 34                  System.out.println("当前线程优先级为:"+i);//5
 35              }
 36          }

线程

        
三.Runnable 接口(java.lang)
     1.概述:Runnable 接口只有二个办法,run方法,由此达成Runnable接口的类,必得重写run方法,不然,语法报错;
     2.兑现接口的功利:
         由于类只好是单世袭(即只现出叁遍extends卡塔尔国,若选拔接口,则达成类能够持续其他类,不占用世襲的任务;
         能够多实现,能够将编写线程类和写职分代码(run(卡塔尔(قطر‎方法卡塔尔的劳作分别开;
     3.定义:
         @FunctionalInterface
         public interface Runnable
     4.方法:
         public void run(卡塔尔国 使用完成接口 Runnable 的对象创设叁个线程时,运转该线程将促成在独立奉行的线程中调用对象的 run 方法
代码演示:     

线程的串行

  1 //通过Runnable接口实现多线程
  2     class MyRunnable implements Runnable{
  3          @Override
  4          public void run(){
  5              for(int i = 0; i<100; i++){
  6                  System.out.println("Smith----------"+i+Thread.currentThread());
  7              }
  8          }
  9      }
 10 
 11      public class RunnableDemo{
 12          public static void main(String[] args){
 13              MyRunnable my = new MyRunnable();
 14             Thread myThread = new Thread(my,"smith");
 15              myThread.start();
 16 
 17              //返回当前线程名称
 18             System.out.println("当前线程:"+Thread.currentThread());
 19 
 20              for(int i = 0;i<100;i++){
 21                  System.out.println("格林:==="+i+Thread.currentThread());
 22              }
 23          }
 24      }

多线程

死锁现象:     

四线程的原理

如果线程非常非常多,会发生什么情况? CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源 每条线程被调度执行的频次会降低(线程的执行效率降低)

  1 class Zhangsan{
  2          public void say(){
  3              System.out.println("张三对李四说:你给你画,我给你书");
  4          }
  5          public void get(){
  6              System.out.println("张三得到画了");
  7          }
  8      }
  9 
 10      class Lisi{
 11          public void say(){
 12              System.out.println("李四对张三说:你给我书,我就给你画");
 13          }
 14          public void get(){
 15              System.out.println("李四得到书了");
 16          }
 17      }
 18      //单例-饿汉式
 19     public class ThreadDeadLock implements Runnable{
 20          private static Zhangsan zs = new Zhangsan();
 21          private static Lisi ls = new Lisi();
 22          private boolean flag = false;
 23          @Override
 24          public void run(){
 25              if(flag){
 26                  synchronized(zs){    //单例模式,所以实例化对象只有一个,可以作为锁使用
 27                     zs.say();
 28                      try{
 29                          Thread.sleep(500);
 30                      }catch(InterruptedException e){
 31                          e.printStackTrace();
 32                      }
 33                      synchronized(ls){
 34                          zs.get();
 35                      }
 36                  }
 37              }else{
 38                  synchronized(ls){
 39                      ls.say();
 40                      try{
 41                          Thread.sleep(500);
 42                      }catch(InterruptedException e){
 43                          e.printStackTrace();
 44                      }
 45                      synchronized(zs){
 46                          ls.get();
 47                      }
 48                  }
 49              }
 50          }
 51          public static void main(String[] args){
 52              ThreadDeadLock t1 = new ThreadDeadLock();
 53              ThreadDeadLock t2 = new ThreadDeadLock();
 54              t1.flag = true;
 55              t2.flag = false;
 56              Thread thA = new Thread(t1);
 57              Thread thB = new Thread(t2);
 58              thA.start();
 59              thB.start();
 60          }
 61      }

八线程的利弊

四.线程安全问题
     原因:当七个线程使用共享的财富时,轻便生出多少安全的问题;
     解决方案:
         Java 提供了3种减轻安全难题的法子;
             1:同步代码块
             2:同步方法
             3:Lock 接口
     1.协助实行代码块        

什么样是主线程

  1  /*使用3个线程,模拟3个窗口,卖100张票;
  2          要求每个线程卖出去的票,不能重复且不能是无效票;
  3          使用一个变量表示100张票,每个窗口卖出去一张票,就将该变量的值减一,直到0为止;
  4          使用同步代码块
  5         */
  6          class MyRunnable implements Runnable{
  7              int ticket = 100;//总票数,只能new一次该类,因为每创建一次对象就会有100张票
  8             @Override
  9              public void run(){
 10                  String name = Thread.currentThread().getName();//获取当前线程名
 11                 while(true){
 12                      synchronized(this){
 13                          if(ticket<=0){
 14                              break;
 15                          }else{
 16                              System.out.println(name+"卖出第"+ticket+"号票");
 17                              ticket--;
 18                          }
 19                      }
 20                  }
 21 
 22              }
 23          }
 24 
 25          public class SellTicket{
 26              public static void main(String[] args){
 27                  //创建任务对象
 28                 MyRunnable my = new MyRunnable();
 29                  //创建线程
 30                 Thread t1 = new Thread(my,"窗口1");
 31                  Thread t2 = new Thread(my,"窗口2");
 32                  Thread t3 = new Thread(my,"窗口3");
 33                  //开启线程
 34                 t1.start();
 35                  t2.start();
 36                  t3.start();
 37              }
 38          }

主导的名词介绍完了

    2.联袂方法         

  1 class MyRunnable implements Runnable{
  2              //定义总票数为成员变量
  3             int ticket = 100;
  4              String name;
  5              @Override
  6              public void run(){
  7                  name = Thread.currentThread().getName();
  8                  //卖票任务
  9                 while(true){
 10                      sell();
 11                      if(ticket<=0){
 12                          break;
 13                      }
 14                  }
 15              }
 16              //同步方法
 17             public synchronized void sell(){
 18                  if(ticket > 0){
 19                      System.out.println(name+"卖出第"+ticket+"号票");
 20                      ticket--;
 21                  }
 22              }
 23          }
 24 
 25          public class SellTicket01{
 26              public static void main(String[] args){
 27                  //创建任务对象
 28                 MyRunnable my = new MyRunnable();
 29                  //创建多线程
 30                 Thread t1 = new Thread(my,"窗口1");
 31                  Thread t2 = new Thread(my,"窗口2");
 32                  Thread t3 = new Thread(my,"窗口3");
 33                  //开启多线程
 34                 t1.start();
 35                  t2.start();
 36                  t3.start();
 37              }
 38          }

    3.Lock 接口        

  1  import java.util.concurrent.locks.Lock;
  2          import java.util.concurrent.locks.ReentrantLock;
  3          class MyRunnable implements Runnable{
  4              //定义票数为成员变量
  5             int ticket = 100;
  6              //创建锁对象
  7             private static final Lock lock = new ReentrantLock();
  8              @Override
  9              public void run(){
 10                  String name = Thread.currentThread().getName();
 11                  while(true){
 12                      lock.lock();
 13                      try{
 14                          if(ticket > 0){
 15                              System.out.println(name+"卖出了第"+ticket+"号票");
 16                              ticket--;
 17                          }else{
 18                              break;
 19                          }
 20                      }finally{
 21                          lock.unlock();
 22                      }
 23                  }
 24              }
 25          }
 26 
 27 
 28          public class SellTicket02{
 29              public static void main(String[] args){
 30                  //创建任务对象
 31                 MyRunnable my = new MyRunnable();
 32                  //创建多线程
 33                 Thread t1 = new Thread(my,"窗口1");
 34                  Thread t2 = new Thread(my,"窗口2");
 35                  Thread t3 = new Thread(my,"窗口3");
 36                  //开启多线程
 37                 t1.start();
 38                  t2.start();
 39                  t3.start();
 40 
 41              }
 42          }

五.运用无名内部类实现三十二线程     

  1 /*编写程序,创建两个线程对象,一根线程循环输出“播放背景音乐”,另一根线程循环输出
  2     “显示画面”,要求线程实现Runnable接口,且使用匿名内部类实现*/
  3      public class ThreadDemo003{
  4          public static void main(String[] args){
  5              new Thread(new Runnable(){
  6                  @Override
  7                  public void run(){
  8                      for(int i = 0; i < 100; i++){
  9                          System.out.println("播放背景音乐");
 10                      }
 11                  }
 12              }).start();
 13 
 14              new Thread(new Runnable(){
 15                  @Override
 16                  public void run(){
 17                      for(int i = 0; i <100; i++){
 18                          System.out.println("显示画面");
 19                      }
 20                  }
 21              }).start();
 22          }
 23      }

  1  /*编写程序,创建两个线程对象,一根线程循环输出“播放背景音乐”,另一根线程循环输出
  2     “显示画面”,要求使用Thread类,且使用匿名内部类实现*/
  3      public  class ThreadDemo03{
  4      public static void main(String[] args){
  5          new Thread(){
  6              @Override
  7              public void run(){
  8                 for(int i = 0; i<100; i++){
  9                      System.out.println("播放背景音乐");
 10                  }
 11              }
 12          }.start();
 13 
 14         new Thread(){
 15              @Override
 16              public void run(){
 17                  for(int i = 0; i<100; i++){
 18                      System.out.println("显示画面");
 19                  }
 20              }
 21          }.start();
 22      }
 23  }
 24 

六.ThreadGroup 类(java.lang)
     简要介绍:线程组:java允许对一群线程实行保管,使用ThreadGroup表示线程组,所无线程均有钦命线程组,若无显式钦点,则为暗中认可线程组.私下认可意况下,子线程和创设他的父线程
         归于同一线程组.意气风发旦某线程到场钦赐线程组内,该线程会一贯归于该组,直至葬身鱼腹,运转进程中不得改革.
     世襲关系:java.lang.Object--java.lang.ThreadGroup
     定义:public class ThreadGroup extends Object implements Thread.UncaughtExceptionHandler
     构造器:
必发365手机版     2.多线程执行的特点。         ThreadGroup(String name): Constructs a new thread group.
         ThreadGroup(ThreadGroup parent, String name): Creates a new thread group.
     常用艺术:
         public int activeCount(){}:Returns an estimate of the number of active threads in this thread group and its subgroups
         public int activeGroupCount(){}:Returns an estimate of the number of active groups in this thread group and its subgroups.
                                         Recursively iterates over all subgroups in this thread group.
         public int enumerate(Thread[] list) Throws SecurityException{}:
         public int enumerate(Thread[] list,boolean recurse)Throws SecurityException{}:Copies into the specified array every active thread
                                                 in this thread group. If recurse is true, this method recursively enumerates all subgroups of
                                                 this thread group and references to every active thread in these subgroups are also included.
                                                 If the array is too short to hold all the threads, the extra threads are silently ignored.
         public final String getName(){}:Returns the name of this thread group.
         public final ThreadGroup getParent()Throws SecurityException{}:Returns the parent of this thread group.
         public final boolean isDaemon(){}:Tests if this thread group is a daemon thread group
         public final void checkAccess() Throws SecurityException{}:Determines if the currently running thread has permission to modify this thread group.
         public final void setDaemon(boolean daemon)Throws SecurityException{}:Changes the daemon status of this thread group.   
    
     代码演示:获取当前系统内运转的所有线程组及线程名        

  1  import java.util.List;
  2          import java.util.ArrayList;
  3          public class ThreadListDemo{
  4              public static void main(String[] args){
  5                  for(String s : getThreadGroups(getRootThreadGroups())){
  6                      System.out.println(s);
  7                  }
  8              }
  9 
 10              //getRootThreadGroups()
 11              public static ThreadGroup getRootThreadGroups(){
 12                  //get current threadgroup
 13                  ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
 14                  while(true){
 15                      if(rootGroup.getParent() != null){
 16                          rootGroup = rootGroup.getParent();
 17                      }else{
 18                          break;
 19                      }
 20 
 21                  }
 22                  return rootGroup;
 23              }
 24 
 25              //getThreadGroups()传入一个线程组,获取该组内所有子线程组
 26             public static  List<String> getThreadGroups(ThreadGroup group){
 27                  List<String> threadList = getThreads(group);//存子线程组名,调用getThreads方法,返回线程组内所有线程名
 28                 ThreadGroup[] groups = new ThreadGroup[group.activeGroupCount()];//活动的线程组名
 29                 int count = group.enumerate(groups,false);//复制子线程组到线程组数据,不递归复制
 30                 for(int i = 0; i< count; i++){
 31                      threadList.addAll(getThreads(groups[i]));
 32                  }
 33                  return threadList;
 34              }
 35 
 36 
 37              //传入一个线程组,返回该组内所有线程名
 38             public static List<String> getThreads(ThreadGroup group){
 39                  List<String> threadList = new ArrayList<>();//存线程名
 40                 Thread[] list = new Thread[group.activeCount()];//活动线程
 41                 int count = group.enumerate(list,false);//复制当前进程到list中
 42                 for(int i = 0; i< count; i++){
 43                      threadList.add("名为:"+group.getName()+"的线程组,线程名为:"+list[i].getName());
 44                  }
 45                  return threadList;
 46              }
 47 
 48          }

七.Executor 接口(java.io.concurrent)
简单介绍:线程池:由于线程涉及到与操作系统交互,所以运维三个新线程的资金财产相比较高,由此,java提供了线程池机制来提升质量,特别是当程序中要求大量生存期比非常的短暂的线程时,应该酌量
     使用线程池.所谓线程池是指在系统运营时即创办大气空闲的线程,程序将二个Runnable对象或Callable对象传给线程池,线程池就能够运营二个线程来实践他们的run或call方法,当方法
     停止时,线程并不会死去,而是重返线程池成为空闲状态,等待试行下一个任务
定义: public interface Executor
方法:public void execute(Runnable command) Throws RejectedExecutionException | NullPointerException {}:Executes the given command at some time in the future
实现类:AbstractExecutorService, ForkJoinPool, ScheduledThreadPoolExecutor, ThreadPoolExecutor
子接口:ExecutorService, ScheduledExecutorService