栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java多线程多种实现方式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java多线程多种实现方式

Java多线程多种实现方式

个人语录:时间不负有心人,星光不问赶路人,以顶级好的态度写一篇博客

上次面试的时候面试官出了一道,多线程的题,自己八股文背多了,实操起来拉胯的一匹,纸上得来终觉浅,明知此事需躬行

文章目录
  • Java多线程多种实现方式
    • 1、继承Thread类实现多线程
      • 常规使用
      • 简便使用:匿名类
      • 区别
      • 案例
    • 2、Runnable接口方式实现多线程
      • 常规使用
      • 简便使用:匿名类
      • 案例
    • 3、Callable和FutureTask获取异步任务
      • Futrue接口
      • Callable接口
      • FutureTask类
      • 案例
      • 线程池实现

1、继承Thread类实现多线程 常规使用
// 步骤1:创建线程类 (继承自Thread类)
   class MyThread extends Thread{

// 步骤2:复写run(),内容 = 定义线程行为
    @Override
    public void run(){
    ... // 定义的线程行为
    }
}

// 步骤3:创建线程对象,即 实例化线程类
  MyThread mt=new MyThread(“线程名称”);

// 步骤4:通过 线程对象 控制线程的状态,如 运行、睡眠、挂起  / 停止
// 此处采用 start()开启线程
  mt.start();
简便使用:匿名类
// 步骤1:采用匿名类,直接 创建 线程类的实例
 new Thread("线程名称") {
                 // 步骤2:复写run(),内容 = 定义线程行为
                    @Override
                    public void run() {       
                  // 步骤3:通过 线程对象 控制线程的状态,如 运行、睡眠、挂起  / 停止   
                      }.start();
区别

案例
public class ThreadDemo {
    public static void main(String[] args) {
        MyThread thread = new MyThread("线程一");
        thread.start();
        MyThread2 thread2 = new MyThread2("线程二");
        thread2.start();
    }
}
class MyThread extends Thread{
    String name ;
    public MyThread(String name){
        this.name = name;
    }
    public void run(){
        System.out.println(name+"正在运行");
    }
}
class MyThread2 extends Thread{
    String name ;
    public MyThread2(String name){
        this.name = name;
    }
    public void run(){
        System.out.println(name+"正在运行");
    }
}
2、Runnable接口方式实现多线程 常规使用
// 步骤1:创建线程辅助类,实现Runnable接口
 class MyThread implements Runnable{
    ....
    @Override
// 步骤2:复写run(),定义线程行为
    public void run(){

    }
}

// 步骤3:创建线程辅助对象,即 实例化 线程辅助类
  MyThread mt=new MyThread();

// 步骤4:创建线程对象,即 实例化线程类;线程类 = Thread类;
// 创建时通过Thread类的构造函数传入线程辅助类对象
// 原因:Runnable接口并没有任何对线程的支持,我们必须创建线程类(Thread类)的实例,从Thread类的一个实例内部运行
  Thread td=new Thread(mt);

// 步骤5:通过 线程对象 控制线程的状态,如 运行、睡眠、挂起  / 停止
// 当调用start()方法时,线程对象会自动回调线程辅助类对象的run(),从而实现线程操作
  td.start();

特别注意:

  • Java中真正能创建新线程的只有Thread类对象
  • 通过实现Runnable的方式,最终还是通过Thread类对象来创建线程

所以对于 实现了Runnable接口的类,称为 线程辅助类;Thread类才是真正的线程类

简便使用:匿名类
    // 步骤1:通过匿名类 直接 创建线程辅助对象,即 实例化 线程辅助类
    Runnable mt = new Runnable() {
                    // 步骤2:复写run(),定义线程行为
                    @Override
                    public void run() {
                    }
                };

                // 步骤3:创建线程对象,即 实例化线程类;线程类 = Thread类;
                Thread mt1 = new Thread(mt, "窗口1");
           
                // 步骤4:通过 线程对象 控制线程的状态,如 运行、睡眠、挂起  / 停止
                mt1.start();.
案例
  • 应用场景:创建两个线程-实现一个耗时任务

  • 实例说明:实现2个窗口同时卖火车票;两个窗口一共卖100张,卖票速度均为1s/张

public class RunableDemo {
    public static void main(String[] args) {
        Runnable1 runnable1 = new Runnable1();
        Thread thread = new Thread(runnable1, "窗口一");
        Thread thread2 = new Thread(runnable1, "窗口二");
        thread.start();
        thread2.start();
    }
}

class Runnable1 implements Runnable {
    private volatile int ticket = 100;

    @Override
    public void run() {
        while (ticket > 0) {
            synchronized (this){
                ticket--;
                System.out.println(Thread.currentThread().getName() + "卖掉1张票,剩余" + ticket + "张票");
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
  
3、Callable和FutureTask获取异步任务

场景: 我们要计算1+…+10和20+…+30相加的结果,当然可以用a=1+…+10,b=20+…+30,之后resutl=a+b。 但实际上第一个任务A和第二个任务B互不影响, 我们可以使用多线程的方法,将任务A和任务B并行执行,最后将两个任务的执行结果相加。那这样怎么用java实现呢?

  • FutureTask和callable是用来干什么的?
  • FutureTask实现并行计算(FutureTask的使用)
Futrue接口
public interface Future {

    //  取消任务。传入的参数为表示若任务开始执行了,是否要尝试中断该线程。参数true为进行尝试中断,false为不进行中断。
    boolean cancel(boolean mayInterruptIfRunning);

    // 获取该任务是否被中断了
    boolean isCancelled();

   //  该任务是否已经完成
    boolean isDone();

    //  获取该任务的返回值,若任务还未完成则会阻塞。
    V get() throws InterruptedException, ExecutionException;

    // 获取任务的返回值,若任务还未完成则会阻塞。参数为指定的阻塞的最长时间,超时会抛出TimeoutException。
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Callable接口
public interface Callable {
    //  Callable只有一个call方法,实现的Callable接口的call方法则为我们要执行的异步任务,V为返回值
    V call() throws Exception;
}

FutureTask类

FutureTask类实现了Future和Runnable接口,是我们实现线程异步执行,并能获取执行结果的封装的实现类。FutureTask有两个构造方法:

  • FutureTask(Callable< V> callalbe): 通常的构造方法,Callable为异步任务,通过futureTask的get()方法可以阻塞地获取任务的返回值。
  • FutureTask(Runnable runnable, V result): runnable为异步任务,result保存了执行结果,当futureTask的get()方法返回的就是result对象。当然,我们若是关心任务是否执行完成而不关心任务的返回值时,可以使用该构造方法。
案例

场景: 我们要计算1+…+10和20+…+30相加的结果,当然可以用a=1+…+10,b=20+…+30,之后resutl=a+b。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutrueDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable callable1= new Callable() {
            int res = 0;
            @Override
            public Integer call() throws Exception {
                for (int i=0;i<=10;i++)
                    res += i;
                return res;
            }
        };
        Callable callable2= new Callable() {
            int res = 0;
            @Override
            public Integer call() throws Exception {
                for (int i=20;i<=30;i++)
                    res += i;
                return res;
            }
        };
        FutureTask task1 = new FutureTask<>(callable1);
        FutureTask task2 = new FutureTask<>(callable2);
        Thread thread1 = new Thread(task1);
        Thread thread2 = new Thread(task2);
        thread1.start();
        thread2.start();
        System.out.println("结果为:"+(task1.get()+task2.get()));
    }

}

线程池实现
import java.util.concurrent.*;

public class FutrueDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        

        Future future1 = executorService.submit(()->{   // 这里线程池submit执行的是call方法,返回的是FutureTask对象
            int res = 0;                                            // 这里用lambda匿名表达式新建了一个Callable的实现
            for (int i = 0; i <= 10; i++) {
                res += i;
            }
            return res;
        });
        Future future2 = executorService.submit(()->{
            int res = 0;
            for (int i = 20; i <= 30; i++) {
                res += i;
            }
            return res;
        });

        System.out.println(future1.get() + future2.get());
    }

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/854662.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号