一.多线程
     1.基本概念
         进程:正在运行中的程序,一个进程中至少包含一个线程
         线程:进程的任务,执行任务的一个通道,一个进程中可以包含多个线程
     2.多线程执行的特点:
         两种方式:分时调度/抢占式调度(java属于抢占)
二.Thread 类(java.lang)
     1.概述:使用该类表示多线程对象,只要创建一个Thread对象,就是一个线程对象产生了
     2.定义:public class Thread extends Object implements Runnable
     3.构造方法:
         Thread():无参构造,分配新的 Thread 对象
         Thread(String name):使用指定的名称分配新的 Thread 对象,设置线程名称
         Thread(Runnable target):接收Runnable接口子类对象,实例化Thread对象
         Thread(Runnable target, String name):接收Runnable接口子类对象,实例化Thread对象,并设置线程名称
     4.静态方法:
         public static Thread currentThread(){}:返回目前正在执行的线程 [线程名,优先级,]
         public static void sleep(long millis) throws InterruptedException{}:使当前线程休眠多少毫秒
         public static void yield(){}:将目前执行的线程暂停,允许其它线程执行
    
     5.常用方法:
         public void run(){}:如果该线程是使用独立的 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      }

死锁现象:

  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
     构造器:
         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

转载于:https://www.cnblogs.com/huguangqin/p/7128802.html

多线程-Thread-Runnable相关推荐

  1. Java多线程——Thread Runnable源码解析

    Java多线程的两种实现方法大家都应该知道了:继承Thread的子类实例化和实现Runnable接口用这个接口实现类去创建Thread实例. Java的线程在Linux平台上使用的是NPTL机制,JV ...

  2. 多线程 -Thread -Runnable -Callable

    多线程(Thread) 线程简介 线程实现 线程状态 线程同步 线程通信问题 高级主题 核心概念 线程就是独立的执行路径; 在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc程; ...

  3. JAVA多线程Thread VS Runnable详解

    进程与线程 进程是程序在处理机中的一次运行.一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不同进程所占用的系统资源相对独立.所以进程是重量级的任务,它们之间的通信和转换都需要操作系统 ...

  4. 线程的创建与启动——Thread 类有两个常用的构造方法:Thread()与 Thread(Runnable)||多线程运行结果是随机的

    线程的创建与启动 在 Java 中,创建一个线程就是创建一个 Thread 类(子类)的对象(实例). Thread 类有两个常用的构造方法:Thread()与 Thread(Runnable).对应 ...

  5. Java多线程-Thread、Runnable、Executor

    线程分为五个阶段:创建.就绪.运行.阻塞.终止. 创建:新建一个线程对象,如Thread thd=new Thread(). 就绪:创建了线程对象后,调用了线程的start()方法(此时线程只是进入了 ...

  6. Java多线程 - Thread和Runnable的区别

    在这我们就不在讲解Thread和Runnable的用法,如果不会的可以去看上一篇文章:<Java实现多线程的几种方式> Runnable是接口. Thread是一个类,继承了Runnabl ...

  7. java多线程实现runnable_Java多线程实现Runnable方式

    本文为大家分享了Java多线程实现Runnable方式的具体方法,供大家参考,具体内容如下 (一)步骤 1.定义实现Runnable接口 2.覆盖Runnable接口中的run方法,将线程要运行的代码 ...

  8. 多线程Thread类创建多线程

    package com.ajax; //多线程Thread类创建多线程 public class Example02 {public static void main(String[] args){n ...

  9. python的多线程threading_Python中多线程thread与threading的实现方法,pythonthreading

    Python中多线程thread与threading的实现方法,pythonthreading 学过Python的人应该都知道,Python是支持多线程的,并且是native的线程.本文主要是通过th ...

  10. 6-7 jmu-Java-07多线程-Thread (3分)

    6-7 jmu-Java-07多线程-Thread (3分) 编写MyThread类继承自Thread.创建MyThread类对象时可指定循环次数n. 功能:输出从0到n-1的整数. 并在最后使用Sy ...

最新文章

  1. 计算机视觉中的自注意力
  2. Java并发编程:阻塞队列
  3. 一生中需要的10种人脉
  4. emca 更改监听端口
  5. Python 最佳实践
  6. JavaScript实现使用 BACKTRACKING 方法查找集合的幂集算法
  7. 干旱的草原与拉大提琴的牧人
  8. AOS编排语言系列教程(六):创建共享云硬盘EVS
  9. (三)在Azure上创建您的第一个Kubernetes集群
  10. 送你一份万字机器学习资料
  11. day 34 进程线程排序 抢票 初级生产者消费者
  12. 数据开发常用的几种数据预处理和数据整理方法
  13. D3入门教程——坐标轴
  14. `CSS filter` 有哪些神奇用途
  15. 成都五月花计算机专业学校单招,成都五月花高级技工学校这所单招学校如何
  16. centos7 npm bulid编译报错解决
  17. 关于武汉蔡甸•九真山第三届登山节活动临时暂停致歉全体参赛及相关工作人员的一封信!
  18. PaddleDetection目标检测之水果检测(下)(yolov3_mobilenet_v1)
  19. 苹果内购退款需要注意的一些东西
  20. 河道治理漂浮物识别监测系统 yolov7

热门文章

  1. QT 5.9.8在ubuntu16.04下安装配置
  2. CTFshow 命令执行 web44
  3. [YTU]_2642 (填空题:类模板---求数组的最大值)
  4. 分段线性插值Python实现(同时估计误差)
  5. 连通图的判断(并查集, DFS, BFS)
  6. php ar 模式,AR技术也被称为什么技术
  7. nRF52 SAADC 直接操作寄存器
  8. ajax不能设置哪些header
  9. SpringMVC核心技术---转发和重定向
  10. Spring命名空间引入方法