首页 > 其他分享 >多线程

多线程

时间:2022-10-19 22:02:08浏览次数:50  
标签:Thread void System 线程 new 多线程 public

多线程基础

  1. 线程简介

    1. 任务

    2. 进程(Process)

      1. 一个进程可以有多个线程

    3. 线程(Thread)

    4. 多线程

    5. 核心

      1. 线程就是独立的执行路径

      2. 在程序运行时,即使没有自己创建的线程,后台也会有多个线程,

      3. main()称之为主线程,为系统的入口,用于执行整个程序

      4. 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能认为的干预的

      5. 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制

      6. 线程会带来额外的开销,如cpu调度时间,并发控制开销

      7. 每个线程在自己的工作仍存交互,仍存控制不当造成数据不一致

  2. 线程实现(重点)

    1. 三种创建方式

      1. 继承Thread(重点)实际上Thread也实现了Runnable接口都得重写run()方法

        1. 线程和mian同时进行(两线程同时进行)

          //创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
          //总结:注意,线程开启不一定立即执行,由CPU调度
          public class TestThread1 extends Thread{
              @Override
              public void run() {
                  //run方法线程体
                  for (int i = 0; i < 20; i++) {
                      System.out.println("我在看代码"+i);
                  }
              }
          ​
              public static void main(String[] args) {
                  //main()线程,主方法
                  //创建一个线程
                  TestThread1 testThread1 = new TestThread1();
                  //线程开始start()方法开启线程
                  testThread1.start();
          ​
                  for (int i = 0; i < 20; i++) {
                      System.out.println("我在学习线程"+i);
                  }
              }
          }
      2. 实现Runnable接口(重点)

        public class TestRunnable1 implements Runnable{
            @Override
            public void run() {
                //run方法线程体
                for (int i = 0; i < 20; i++) {
                    System.out.println("我在看代码"+i);
                }
            }
        ​
            public static void main(String[] args) {
                //main()线程,主方法
                //创建一个线程
                TestRunnable1 testRunnable1=new TestRunnable1();
        //        Thread thread = new Thread(testRunnable1);
        //        thread.start();
                //线程开始start()方法开启线程
                new Thread(testRunnable1).start();
        ​
                for (int i = 0; i < 20; i++) {
                    System.out.println("我在学习线程"+i);
                }
            }
        }
      3. 小结:

        1. 继承Thread类

          1. 子类继承Thread类具备多线程能力

          2. 启动线程:子类对象.start()

          3. 不建议使用:避免OOP单继承局限性

        2. 实现Runnable接口

          1. 实现接口Runnable具备多线程能力

          2. 启动线程:传入目标对象+Thread对象.start()。

          3. 推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用

          public class TestRunnable2 implements Runnable{
              private int sum=10;
              @Override
              public void run() {
                  while (true){
                      if (sum<=0){
                          break;
                      }
                      try {
                          Thread.sleep(200);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println(Thread.currentThread().getName()+
                              "---->拿到了第"+sum--+"票");
                  }
              }
          ​
              public static void main(String[] args) {
                  TestRunnable2 testRunnable2=new TestRunnable2();
                  new Thread(testRunnable2,"小明").start();
                  new Thread(testRunnable2,"黄牛党").start();
                  new Thread(testRunnable2,"小辉").start();
              }
          }
      4. 龟兔赛跑(我们是上帝)

        public class Race implements Runnable {
            private static String name;
        ​
            @Override
            public void run() {
                for (int i = 0; i <= 100; i++) {
                    //模拟兔子休息
                    if (Thread.currentThread().getName().equals("兔子") && i % 10 == 0) {
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    //判断比赛是否结束
                    boolean flag = gameOver(i);
                    //如果比赛结束了,就结束程序
                    if (flag) {
                        break;
                    }
                    System.out.println(Thread.currentThread().getName() + "--->跑了" + i + "步");
                }
            }
            private boolean gameOver(int steps) {
                //判断是否由胜利者
                if (name != null) {
                    return true;
                } else if (steps == 100) {
                    //已经存在是胜利者
                    name = Thread.currentThread().getName();
                    System.out.println("winner is " + name);
                    return true;
                }
                return false;
            }
        ​
            public static void main(String[] args) {
                Race race = new Race();
                new Thread(race, "兔子").start();
                new Thread(race, "乌龟").start();
            }
        }
      5. 实现Callable接口

        1. 实现Callable接口,需要返回值类型

        2. 重写call方法,需要抛出异常

        3. 创建目标对象

        4. 创建执行服务:ExecutorService ser=Executors.newFixedThreadPool(1);

        5. 提交执行:Future<Boolean> result1=ser.submit(t1);

        6. 获得结果:boolean r1=result1.get();

        7. 关闭服务:ser.shutdownNow();

          package com.lyh.demo02;
          ​
          ​
          ​
          import org.apache.commons.io.FileUtils;
          ​
          import java.io.File;
          import java.io.IOException;
          import java.net.URL;
          import java.util.concurrent.*;
          ​
          public class TestCallable implements Callable<Boolean> {
              private String url;//网络图片地址
              private String name;//保存的文件名
              public TestCallable(String url,String name){
                  this.url=url;
                  this.name=name;
              }
              @Override
              public Boolean call() {
                  webDownLoader webDownLoader=new webDownLoader();
                  webDownLoader.downloader(url,name);
                  System.out.println("下载了文件名为:"+name);
                  return true;
              }
              public static void main(String[] args) throws ExecutionException, InterruptedException {
                  TestCallable t1=new TestCallable("http://browser9.qhimg.com/bdm/0_0_100/t01b30dd1843479c87c.jpg","1.jpg");
                  TestCallable t2=new TestCallable("http://browser9.qhimg.com/bdm/0_0_100/t01b30dd1843479c87c.jpg","2.jpg");
                  TestCallable t3=new TestCallable("http://browser9.qhimg.com/bdm/0_0_100/t01b30dd1843479c87c.jpg","3.jpg");
                  //1. 创建执行服务:
                  ExecutorService ser = Executors.newFixedThreadPool(3);
                  //2. 提交执行:
                  Future<Boolean> r1 = ser.submit(t1);
                  Future<Boolean> r2 = ser.submit(t2);
                  Future<Boolean> r3 = ser.submit(t3);
                  //3. 获得结果:
                  Boolean rs1 = r1.get();
                  Boolean rs2 = r2.get();
                  Boolean rs3 = r3.get();
          ​
                  //4. 关闭服务:
                  ser.shutdownNow();
              }
          }
          //下载器
          class webDownLoader{
              //下载方法
              public void downloader(String url,String name){
                  try {
                      FileUtils.copyURLToFile(new URL(url),new File(name));
                  } catch (IOException e) {
                      e.printStackTrace();
                      System.out.println("IO异常,downloader方法出现问题");
                  }
              }
          }
  3. 线程状态

    1. 新建状态---就绪状态---运行状态---阻塞状态---就绪状态

    2. 新建状态---就绪状态---运行状态--就绪状态---死亡状态

    3. 线程停止

    4. 线程休眠

      1. sleep(时间)指定当前线程阻塞的毫秒数

      2. sleep存在异常InterruptedException

      3. sleep时间达到后线程进入就绪状态

      4. sleep可以模拟网络延迟,倒计时

      5. 每一个对象都有一个锁,sleep不会释放锁;

      6. 代码实现

        package com.lyh.state;
        ​
        import java.text.SimpleDateFormat;
        import java.util.Date;
        ​
        public class TestSleep {
            //打印当前系统时间
            public static void main(String[] args) {
                Date date = new Date(System.currentTimeMillis());
                while (true){
                    try {
                        Thread.sleep(1000);
                        System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
                        date = new Date(System.currentTimeMillis());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        ​
        ​
            //模拟倒计时时间
            public static void tenDown() throws InterruptedException {
                int num=10;
                while (true){
                    Thread.sleep(10000);
                    System.out.println(num--);
                    if (num<=0){
                        break;
                    }
                }
            }
        }
    5. 礼让

      1. 代码实现

        public class TestYield implements Runnable{
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"线程开始了");
                //礼让方法
                Thread.yield();
                System.out.println(Thread.currentThread().getName()+"线程结束了");
            }
        ​
            public static void main(String[] args) {
                TestYield yield = new TestYield();
                new Thread(yield,"a").start();
                new Thread(yield,"b").start();
            }
        }
    6. join()(开辟vip通道)

      1. 代码实现

        package com.lyh.state;
        ​
        public class TestJoin implements Runnable {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("我是vip" + i);
                }
            }
        ​
            public static void main(String[] args) throws InterruptedException {
                TestJoin testJoin = new TestJoin();
                Thread thread = new Thread(testJoin);
                thread.start();
                //主线程
                for (int i = 0; i < 50; i++) {
                    if (i == 200) {
                        thread.join();//插队
                    }
                    System.out.println("我是main" + i);
                }
            }
        }
    7. State()观测线程状态

      //观察线程状态
      public class TestState {
          public static void main(String[] args) throws InterruptedException {
              Thread thread = new Thread(()->{
                  for (int i = 0; i < 5; i++) {
                      try {
                          Thread.sleep(1000);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
                  System.out.println("加油加油加油");
              });
      ​
              //观察状态
              Thread.State state = thread.getState();
              System.out.println(state);
      ​
              //观察后启动
              thread.start();
              state=thread.getState();//更新线程状态
              System.out.println(state);
              //只要线程不终止,就一直执行state!=Thread.State.TERMINATED
              while (state!=Thread.State.TERMINATED){
                  Thread.sleep(100);
                  state=thread.getState();//更新线程状态
                  System.out.println(state);
              }
          }
      }
    8. 线程优先级:setPriority():设置优先级

      1. 代码实现

        /**
         * setPriority();设置优先级,最高为10
         * getPriority() 获取优先级
         */
        public class TestPriority {
            public static void main(String[] args) {
                //主线程默认优先级
                System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
                myPriority myPriority = new myPriority();
                Thread thread0 = new Thread(myPriority);
                Thread thread1 = new Thread(myPriority);
                Thread thread2 = new Thread(myPriority);
        ​
                //先设置优先级在启动
                thread0.start();
        ​
                thread1.setPriority(5);
                thread1.start();
        ​
                thread2.setPriority(Thread.MAX_PRIORITY);//最高优先级
                thread2.start();
        ​
        ​
        ​
            }
        ​
        }
        ​
        class myPriority implements Runnable {
        ​
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
            }
        }
  4. 线程同步(重点)

    1. 对可能出现线程安全的代码,用锁把它锁定,代码执行完毕后释放锁,让其他线程进来执行。这样可以解决安全问题。不能让多个线程同时去操作共享的变量,在一个线程执行完代码前,不让其他线程进入执行代码。

    2. synchronized锁,解决线程不安全(假设有三个线程t1、t2、t3,怎么保证让t1执行完毕后执行t2,t2执行完毕后执行t3线程?)

      //假设有三个线程t1、t2、t3,怎么保证让t1执行完毕后执行t2,t2执行完毕后执行t3线程?
      public static void main(String[] args) {
          //1.子线程
          Thread thread = new Thread(new Runnable() {
              @Override
              public void run() {
                  for (int i = 0; i < 10; i++) {
                      try {
                          Thread.sleep(10);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println(Thread.currentThread().getName()
                              +"i:"+i);
                  }
              }
          });
          //2.子线程
          Thread thread1 = new Thread(new Runnable() {
              @Override
              public void run() {
                  try {
                      thread.join();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  for (int i = 0; i < 10; i++) {
                      try {
                          Thread.sleep(20);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println(Thread.currentThread().getName()
                              +"i:"+i);
                  }
              }
          });
          //3.子线程
          Thread thread2 = new Thread(new Runnable() {
              @Override
              public void run() {
                  try {
                      thread1.join();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  for (int i = 0; i < 20; i++) {
                      try {
                          Thread.sleep(200);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println(Thread.currentThread().getName()
                              +"i:"+i);
                  }
              }
          });
          thread.start();
          thread1.start();
          thread2.start();
      }
    1. 测试JUC安全类型的集合

      public class TestJUC {
          public static void main(String[] args) throws InterruptedException {
              CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
              new Thread(() -> {
                  for (int i = 0; i < 10000; i++) {
                      list.add(Thread.currentThread().getName());
                  }
              }).start();
              Thread.sleep(1000);
              System.out.println(list.size());
          }
      }

标签:Thread,void,System,线程,new,多线程,public
From: https://www.cnblogs.com/lyhidea/p/16807975.html

相关文章

  • 多线程 学习
    ​​http://www.vchome.net/dotnet/dotnetdocs/dotnet1.htm​​作者:沐雪文章均系作者原创或翻译,如有错误不妥之处,欢迎各位批评指正。本文版权归作者有,如需......
  • 常用的多线程类
    常用的多线程类创建池ExecutorServiceexecutor=Executors.newFixedThreadPool(4);Executors工程类,可以提交任务。executor.submit(Callabletask)记得关闭池shut......
  • 【Java】多线程详解!
    多线程程序程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。进程进程(process)是程序的一次执行过程,或是正在运行的一个......
  • Python中的多线程
    线程和进程线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线进程之间相互独立,但同一线程......
  • Java 多线程(九)死锁及Lock
    死锁多个线程各自站有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形,某一个同步块同时拥有“两个......
  • 多线程的作用
    多线程的作用发挥多核CPU的优势随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU......
  • Java 多线程(八)同步方法及同步块
    同步方法由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们需要针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized方......
  • 多线程间的5种通信
    一、使用volatile关键字基于volatile关键字来实现线程间相互通信是使用共享内存的思想。大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候,线程能够感......
  • Java 多线程(七)三大不安全案例
    一,买票//不安全买票publicclassUnsafeBuyTickets{publicstaticvoidmain(String[]args){BuyTicketsbuyTickets=newBuyTickets();new......
  • Java 多线程(六)线程同步
    并发同一个对象被多个线程同时操作  线程同步现实生活中,我们会遇到同一个资源,多个人都想使用的问题。比如,食堂排队打饭,每个人都想吃饭最天然的解决办法就是......