多线程基础

  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());
          }
      }

原文地址:http://www.cnblogs.com/lyhidea/p/16807975.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性