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

开辟线程的方式到底有几种呢???看起来好多种,实际上.....

Java 更新时间:发布时间: 百科书网 趣学号

开辟线程的方式
  • 上代码
    • 细说线程池------>>
      • 类的继承实现关系--->
    • 接口描述-->>
    • 接口中的方法-->
  • 带有返回值的Thread开启之路------>>FutureTask
    • 构造 函数
    • FutureTask类中的方法------->>>>
  • 小结----线程的启动方式

上代码
package com.thread.gavin.ThreadDemo;
import java.util.concurrent.*;

class T extends Thread {
    @Override
    public void run() {
        System.out.println("T----start");
    }
}
class P implements Runnable {
    @Override
    public void run() {
        System.out.println("P----start");
    }
}
class F implements  Callable{
    @Override
    public String call() throws Exception {
        String success="Callable----start";
        System.out.println(success);
        return success;
    }
}

public class ThreadStart {
    public static void main(String[] args) {
        //第一种-----继承Thread
        new T().start();
//        第二种实现Runnable接口,本质上是借助Thread的start方法
        new Thread(new P()).start();
//        第三种 lambda
        new Thread(() -> {
            System.out.println("匿名----start");
        }).start();
//第四种 实现Callable接口, 实现call方法,可以指定返回值的   线程开启本质上是借助Thread的start方法
new Thread(new FutureTask(new F())).start();
//第五种 线程池
        ExecutorService service= Executors.newCachedThreadPool();
       Thread thread= new Thread(()->{
               System.out.println("线程池中的线程开启了");
       });
   service.execute(thread);//假如线程池
        service.submit(thread);
   Future f=service.submit(new F());
   service.shutdown();
    }
}

细说线程池------>> 类的继承实现关系—>

ExecutorService---->>>>>这是一个接口,
用于执行线程池中的线程
public interface ExecutorService extends Executor

接口描述–>>

提供管理终止的方法和方法的执行者,未来可生成跟踪一个或多个异步任务进度的。

接口中的方法–>

List invokeAll​(Collection
tasks)
执行给定任务,在全部完成后返回保留其状态和结果的期货列表。

简而言之就是实现Callable接口的类作为一个集合, 执行集合里所有的线程,由于实现Callable接口要实现Call()方法,并且带有返回值,所以会有一个List集合来接收所有返回值;

List invokeAll​(Collection
tasks, long timeout, TimeUnit unit)

执行给定任务,在全部完成或超时到期时返回保留其状态和结果的期货列表,以先发生者为准。

简而言之就是任务完成/超时时做出的一些处理
第一个参数是实现Callable接口的类作为一个集合,第二个是设施超时的等待时间,第三个是设置超时的计时单位;返回值也是一个List集合’

话不多说,既然有了方法,那就去实现一下子呗;
分析一下,Callable是一个接口,而invokeAll需要传入的是一个Collection集合,集合里面的元素是继承Callable接口的的,说明是Callable的子类或者孙子类

@FunctionalInterface
public interface Callable

但是阅读API发现,callable接口是一个功能性接口,并没有直接实现的子类 那怎么办?只能手动写类取实现Callable接口

然后开始写一些关于invokeAll的
List invokeAll​(Collection
tasks)

package TreeB;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

class Person implements Callable {
    @Override
    public String call() throws Exception {
        Random random = new Random();
        int i = random.nextInt(10);
        TimeUnit.SECONDS.sleep(i);
        return "我在学习----" + i;
    }
}
public class ThreadPoolDemo {
    public static void main(String[] args)  {
        //开辟一个线程池
        ExecutorService service = Executors.newCachedThreadPool();
//        准备线程----带返回值的
        List list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(new Person());
        }
        List> futures = null;
        try {
            futures = service.invokeAll(list);
            //futures = service.invokeAll(list, 8, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("参与工作的CPU核心数--"+Runtime.getRuntime().availableProcessors());
        //遍历
        for (Future fu :
                futures) {
            String str = null;
            try {
                str = fu.get();
                System.out.println(str);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
      service.shutdown();
    }
}

List invokeAll​(Collection
tasks, long timeout, TimeUnit unit)

超时时间是针对的所有线程而言,而不是单个线程的超时时间。如果超时,会取消没有执行完的所有任务,并抛出超时异常。
如果任务处理超时了,会发生什么呢?
简单修改一下------

package TreeB;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

class Person implements Callable {
    @Override
    public String call() throws Exception {
        Random random = new Random();
        int i = random.nextInt(10);
        TimeUnit.SECONDS.sleep(i);
        return "我在学习----" + i;
    }
}

public class ThreadPoolDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //开辟一个线程池
        ExecutorService service = Executors.newCachedThreadPool();
//        准备一个线程就够了吧----带返回值的
        List list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(new Person());
        }
        List> futures = service.invokeAll(list, 3, TimeUnit.SECONDS);
        //遍历---为了看得到结果
        for (Future fu :
                futures) {
            String str = fu.get();
            System.out.println(str);
        }
        service.shutdown();
    }
}

为了在控制台上看到结果,使用了get来获取程序执行的返回值,(是在get这里报的异常)可以看到本次只有三个线程执行了,其他线程被取消了;

T invokeAny​(Collection tasks) throws
InterruptedException, ExecutionException

执行给定任务,返回已成功完成的任务的结果(即,无一例外),如果有的话。正常或特殊返回时,未完成的任务将被取消。如果在此操作进行期间修改了给定的集合,则此方法的结果未定义

简言之就是返回已经执行成功的线程的返回值的一个;返回第一个执行完的值

T invokeAny​(Collection tasks, long
timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException
执行给定任务,返回已成功完成的任务的结果(即无一例外),如果在给定超时之前执行任何任务。正常或特殊返回时,未完成的任务将被取消。如果在此操作进行期间修改了给定的集合,则此方法的结果未定义。

invokeAny超时是怎么处理的呢?
如果没有任务完成则会抛出-----

java.util.concurrent.ExecutionException:******************

应用场景------需要最短的时间内返回(线程执行最快的)结果,

boolean isShutdown()
如果此执行器已关闭,则返回。true
---------------------------------------------------------------------
boolean isTerminated()
如果所有任务在关闭后完成,则返回。true

isShutdown() ----用于检测线程执行器是否关闭


isTerminated() 用于检测线程是否都已经执行完毕

关闭启动器,无返回值

void shutdown()
启动有序关闭,执行以前提交的任务,但不会接受任何新任务。

1、停止接收新的submit的任务;
2、已经提交的任务(包括正在跑的和队列中等待的),会继续执行完成;
3、等到所有任务执行完成后,才真正停止;

强制关闭启动器,有返回值

List shutdownNow() 试图阻止所有积极执行的任务,停止处理等待任务,并返回等待执行的任务列表。

1、跟 shutdown() 一样,先停止接收新submit的任务;

2、忽略队列里等待的任务;

3、尝试将正在执行的任务interrupt中断;

4、返回未执行的任务列表;

修改后代码如下—

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

class Person implements Callable {
    @Override
    public String call() throws Exception {
        Random random = new Random();
        int i = random.nextInt(10);
    TimeUnit.SECONDS.sleep(1);
        //throw new RuntimeException();
        return "我在学习----" + i;
    }
}

public class ThreadPoolDemo {
    public static void main(String[] args) {
        //开辟一个线程池
        ExecutorService service = Executors.newCachedThreadPool();
//        准备一个线程就够了吧----带返回值的
        List list = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            list.add(new Person());
        }
        try {
            List> futures1 = service.invokeAll(list);
            //执行完在返回结果
            for (Future ff :
                    futures1) {
                String s = ff.get();
//                System.out.println(s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("---------------------");
        List runnables =null;
        if(!service.isTerminated()){
            runnables= service.shutdownNow();
        }
        Iterator iterator = runnables.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next().toString());
        }
    }
}

结果是所有线程都执行完毕,但是shutdownNow的返回值列表并不为null,这是什么原因呢?
猜想------->可能是线程最后都执行完毕了,因为代码中线程并没有对Interrupt()做出响应

任务的提交----->>

Future submit​(Runnable task)
提交可执行的任务,未来并返回代表该任务的返回值。

Future submit​(Runnable task, T result)
提交可执行的任务,未来并返回代表该任务的返回值。

Future submit​(Callable task)
提交价值回报任务以执行,未来并返回代表任务待决结果的返回值。

参数可以传Runnable和Callable

shutdown()与shutdownNow()的异同点---------->>>

  1. shutdown与shutdownNow 都是立即返回并且拒绝接受新任务;
  2. shutdown等待任务全部结束;shutdownNow是试图结束所有任务—(包括正在运行的与没有运行的)但不保证能结束;
带有返回值的Thread开启之路------>>FutureTask

一个实现Runnable且带有返回值的类—FutureTask

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class TTT implements Callable {
    @Override
    public String call() throws Exception {
       
        return "success";
    }
}
public class Tead {
    public static void main(String[] args) {
       FutureTaskfutureTask= new FutureTask(new TTT());
       new Thread(futureTask).start();
        try {
            String s = futureTask.get();
            System.out.println(s);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

在这个案例中,用Thread 实例中传入了FutureTask,一次来得到返回值,这种方式其实也是绕了一圈,传入的FutureTask中其实是有实现Callable接口的的,但不管怎样,我们来看类的信息;

public class FutureTask extends Object implements RunnableFuture

FutureTask实现了Future接口,FutureTask提供了启动和取消异步任务,查询异步任务是否计算结束以及获取最终的异步任务的结果的一些常用的方法。通过get()方法来获取异步任务的结果,但是会阻塞当前线程直至异步任务执行结束。一旦任务执行结束,任务不能重新启动或取消,除非调用runAndReset()方法

public interface RunnableFuture extends Runnable, Future

构造 函数

FutureTask​(Runnable runnable, V result)
创建一个在运行时执行给定结果,并在成功完成时返回给定结果的安排。

V result表示运行结束后的返回值

public class Tead {
    public static void main(String[] args) {
      FutureTask f= new FutureTask(new Runnable() {
          @Override
          public void run() {
              for (int i = 0; i < 5; i++) {
                  System.out.println(i);
              }
          }
      },"完成了");//运行结束后会返回"完成了"
      new Thread(f).start();
        try {
            Object o = f.get();
            System.out.println(o);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

FutureTask​(Callable callable)
创建一个FutureTaskCallable,返回值将在运行时给定。

FutureTask ff= new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                return "success";
            }
        });
        new Thread(ff).start();
        try {
            Object of = ff.get();
            System.out.println(of);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

FutureTask类中的方法------->>>>
V	get()	
//如有必要,等待计算完成,然后检索其结果。
V	get​(long timeout, TimeUnit unit)	
///如果需要,最多等待给定时间才能完成计算,然后在可用时检索其结果。

protected boolean runAndReset()
执行计算而不设置其结果,然后将此Future重置为初始状态,如果计算遇到异常或被取消,则未执行该状态
这是个什么鬼?

protected void set​(V v)
将此Future的结果设置为给定值,除非此Future已经设置或已取消。

protected void done()
当此任务过渡到状态(正常或通过取消)时调用受保护的方法。isDone

protected void setException​(Throwable t)
导致此未来报告执行例外与给定可投掷的原因,除非此未来已经设置或已取消。

String toString() 返回此未来任务的字符串表示。

小结----线程的启动方式

覆写/实现run()方法
1,继承Thread类-----
new MyThread().start();
2,new Thread®.start; 其中r可以是lambda,可以实现runnable接口也可以是继承Thread的类
3,ThreadPool 线程池的方式
4,Future Callable以及FutureTask

但是归根结底就是
描述一------->>>>>继承Thread/实现Runnable/Callable
描述二----------->>>>>覆写run()/call()方法

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

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号