瑞星 发表于 2023-4-4 14:04:37

多线程

多线程

多线程概述


[*]多线程就是计算机用时运行多个任务
[*]但实质上,同一个时间点,只会运行一个任务,只是计算机在不同任务之间来回切换而已。
并发和并行

并行:在同一时间,多个任务分别在多个CPU上进行。
并发:在同一时间,多个任务在同一个CPU交替进行。
线程和进程

进程

[*]独立性:进程是一个独立运行的应用程序。
[*]动态性:进程就是一个程序运行的过程,程序开始运行,进程创建,运行接收,进程消亡。
[*]并发性:任何进程可以和其他进程并发执行。
线程不能单独存在,线程是进程的一部分,一个进程可以有多可线程,但必须至少有一个线程。
多线程实现


[*]实现多线程方式一:继承Thread类,Thread类就是线程类,要实现多线程必须创建Thread类对象。
自定义类通过继承Thread类,再重写run() 方法
public class ThreadDemo extends Thread{
    @Override
    public void run() {
      for (int i = 0; i < 100; i++) {
            System.out.println(getName()+"的第"+i+"次");
      }
    }
}在测试类中创建自定义类对象
public class TestDemo {
    public static void main(String[] args) {
      ThreadDemo t1 = new ThreadDemo();
      //为线程设置名字
      t1.setName("线程1");
      //start() 方法告诉JVM程序会启用多线程,并自动调用run() 方法
      //直接执行run() 方法,那么就是执行一个普通的单线程方法
      t1.start();

      ThreadDemo t2 = new ThreadDemo();
      t2.setName("线程2");
      t2.start();
    }
}
[*]实现多线程方式二:实现Runnable接口
public class RunnableDemo implements Runnable{
    @Override
    public void run() {
      for (int i = 0; i < 100; i++) {
            //让线程停止指定毫秒数
            //父类Thread没有抛出异常,所以子类只能自己捕获异常
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            //调用Thread的静态方法currentThread(),可以直接获取当前的进程
            System.out.println("这是线程"+Thread.currentThread().getName()+i);
      }
    }
}测试类
public class TestDemo2 {
    public static void main(String[] args) {
      RunnableDemo ra = new RunnableDemo();

      //调用Thread() 的带参方法,传入一个Runnable的实现类对象
      Thread thread = new Thread(ra);
      thread.setName("西安");
      //为该线程设置优先级1(min)-10(max),优先级越高,抢占CPU的几率就越大,但不会达到100%
      thread.setPriority(10);
      //获取优先级
      System.out.println(thread.getPriority());
      thread.start();
      
      Thread thread2 = new Thread(ra);
      thread2.setPriority(1);
      //获取优先级
      System.out.println(thread2.getPriority());
      thread2.setName("杭州");
      thread2.start();
    }
}
[*]实现Callable接口
public class CallableDemo implements Callable<String> {
    @Override
    public String call() throws Exception {
      for (int i = 0; i < 100; i++) {
            System.out.println("和班主任请假第"+i+"次");
      }
      return "同意";
    }
}测试类
public class TestDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
      CallableDemo cd = new CallableDemo();
      FutureTask<String> ft = new FutureTask<>(cd);
      Thread thread = new Thread(ft);
      thread.start();
      FutureTask<String> ft2 = new FutureTask<>(cd);
      Thread thread2 = new Thread(ft2);
      thread2.start();
      //注意如果在start方法之前 调用get() 方法,意味着在开启线程之前获取返回值,但是此时线程尚未开启,这就照成死锁
      String o = ft.get();
      String o2 = ft2.get();
      System.out.println(o);
      System.out.println(o2);
    }
}总结如下:


[*]方式一:通过自定义类继承Thread的方式。
优点:子类可以直接调用父类的方法,缺点,对子类限制比较大,不能再继承其他类

[*]方式二   :通过自定义类实现Runnable接口的方式。
优点:通过实现接口的方式,子类还可以继承其他类,拓展性更强
缺点:不能直接启用多线程,需要先创建Runnable实现类对象,再使用Thread的带参构造传入Runnable实现类对象,再通过Thread对象启用多线程

[*]方式三:通过自定义类实现Callable接口的方式
优点:通过实现接口的方式,子类还可以继承其他类,执行线程后还可以返回值
缺点:不能直接启用多线程,需要先需要先创建Callable实现类对象,再使用FutureTask的带参构造传入Runnable实现类对象,再使用Thread的带参构造传入FutureTask类对象,再通过Thread对象启用多线程
守护线程

守护线程会因为普通线程结束而结束,无论守护线程是否执行完毕
代码如下:
public class DaemonDemo {
    public static void main(String[] args) {
      Test1 t1 = new Test1();
      t1.setName("主人");
      t1.setPriority(1);
      t1.start();
      
      Test2 t2 = new Test2();
      t2.setDaemon(true);
      t2.setName("保镖");
      t2.setPriority(10);
      t2.start();
    }
}
/**
* 主人线程
*/
public class Test1 extends Thread{
    @Override
    public void run() {
      for (int i = 0; i < 10; i++) {
            System.out.println(getName()+"..."+i);
      }
    }
}
/**
* 保镖线程
*/
public class Test2 extends Thread{
    @Override
    public void run() {
      try {
            Thread.sleep(3);
      } catch (InterruptedException e) {
            throw new RuntimeException(e);
      }
      for (int i = 0; i < 100; i++) {
            System.out.println(getName()+"==="+i);
      }
    }
}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 多线程