❶ 创建多线程有几种方法
1、通过继承Thread类创建线程
(1).首先定义一个类去继承Thread父类,重写父类中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2).直接创建一个ThreadTest类的对象,也可以利用多态性,变量声明为父类的类型。
(3).调用start方法,线程启动,隐含的调用run()方法。
[java]view plain
{
publicvoidrun(){
for(inti=0;i<=10;i++){
System.out.println(i);
}
}
publicstaticvoidmain(String[]args){
ThreadTestthread1=newThreadTest();
ThreadTestthread2=newThreadTest();
thread1.start();
thread2.start();
}
}
2、通过实现Runnable接口创建线程
(1).定义一个类实现Runnable接口,重写接口中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2).创建Runnable接口实现类的对象。
(3).创建一个ThreadTest类的对象,需要封装前面Runnable接口实现类的对象。(接口可以实现多继承)
(4).调用Thread对象的start()方法,启动线程
[java]view plain
{
@Override
publicvoidrun(){
for(inti=0;i<=10;i++){
System.out.println(i);
}
}
publicstaticvoidmain(String[]args){
ThreadTestthreadTest=newThreadTest();
Threadtheard=newThread(threadTest);
theard.start();
}
}
3.通过Callable和Future创建线程
(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并启动新线程。
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
[java]view plain
<Integer>{
@Override
publicIntegercall()throwsException{
intcount=0;
for(inti=0;i<=10;i++){
count=count+i;
}
returncount;
}
publicstaticvoidmain(String[]args)throwsInterruptedException,ExecutionException{
ThreadTesttest=newThreadTest();
FutureTask<Integer>thread=newFutureTask<>(test);
newThread(thread,"有返回值的线程").start();
System.out.println(thread.get());
}
}
使用实现Runnable接口方式创建线程可以共享同一个目标对象(TreadDemo1 tt=new TreadDemo1();),实现了多个相同线程处理同一份资源。
然后再看一段来自JDK的解释:
TheRunnableinterface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments calledrun.
This interface is designed to provide a common protocol for objects that wish to execute code while they are active. For example,Runnableis implemented by classThread. Being active simply means that a thread has been started and has not yet been stopped.
In addition,Runnableprovides the means for a class to be active while not subclassingThread. A class that implementsRunnablecan run without subclassingThreadby instantiating aThreadinstance and passing itself in as the target. In most cases, theRunnableinterface should be used if you are only planning to override therun()method and no otherThreadmethods. This is important because classes should not be subclassed unless the programmer intends on modifying or enhancing the fundamental behavior of the class.
采用实现Runnable、Callable接口的方式创见多线程时,优势是:
线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。
在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
劣势是:
采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。
❷ 多线程的定义是什么
线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。
多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度。
多线程是多任务的特殊形式。通常,有两种类型的多任务:基于进程和基于线程的多任务。进程本质上是正在执行的程序。因此,基于进程的多任务就是允许您的计算机同时运行两个或者更多程序的特性。例如,基于进程的多任务允许您在使用电子制表软件或者浏览Internet的同时运行文字处理程序。在基于进程的多任务中,程序是调度程序可以分派的最小代码单元。
多线程是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率。线程是在同一时间需要完成多项任务的时候被实现的。
使用线程的好处有以下几点:
·使用线程可以把占据长时间的程序中的任务放到后台去处理
·用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
·程序的运行速度可能加快
·在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较游泳了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。
还有其他很多使用多线程的好处,这里就不一一说明了。
多线程应用
我们以客户/服务器应用模式中如何进行服务器程序设计为例,来说明多线程技术的应用。该程序是在DECnet-VAX网络邮箱上实现的。对于TCP/IP,除了改用捆绑的套接字(socket)来代替DECnet中的网络邮箱以监视客户的服务请求外,其他方面基本上是一样的。
为了简化说明,假定该服务程序只提供2类功能,分别由函数funcl( )和func2( )来实现。客户在请求服务时要指明功能号1或2。另外限制需要同时提供服务的客户数目。
多线程程序的基本设计思想是,为请求服务的每个客户建立1个线程,专门为该客户提供服务。限制客户数目就是限制同时存在的线程数目。这些动态建立的线程对象存放在数组中。通过查找该数组是否有空槽,来决定是否达到最大数目。同时利用该数组来管理这些动态存在的线程及相应的网络链路。整个程序由1个主程序和提供2类服务的2个子程序组成。主程序(主控线程)在完成初始化操作后,开始循环读取邮箱中的网络控制信息;在接收到连接请求信息后,主控线程就建立1个新线程,并指定相应的函数作为执行代码;如果客户要断开连接,则主控线程查找到相应的服务线程号,释放该服务线程使用的网络链路,并删除此线程。
❸ java中什么叫做线程什么叫多线程多线程的特点是什么
线程的概念:Thread 每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。
多线程的概念: 多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。
多线程的特点:使用线程可以把占据长时间的程序中的任务放到后台去处理
用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度 。
程序的运行速度可能加快 ·在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。
在这种情况下我们可以释放一些珍贵的资源如内存占用等等。
❹ 多线程是什么
1.多线程的概念?
说起多线程,那么就不得不说什么是线程,而说起线程,又不得不说什么是进程。
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
进程可以简单的理解为一个可以独立运行的程序单位。它是线程的集合,进程就是有一个或多个线程构成的,每一个线程都是进程中的一条执行路径。
那么多线程就很容易理解:多线程就是指一个进程中同时有多个执行路径(线程)正在执行。
为什么要使用多线程?
1.在一个程序中,有很多的操作是非常耗时的,如数据库读写操作,IO操作等,如果使用单线程,那么程序就必须等待这些操作执行完成之后才能执行其他操作。使用多线程,可以在将耗时任务放在后台继续执行的同时,同时执行其他操作。
2.可以提高程序的效率。
3.在一些等待的任务上,如用户输入,文件读取等,多线程就非常有用了。
缺点:
1.使用太多线程,是很耗系统资源,因为线程需要开辟内存。更多线程需要更多内存。
2.影响系统性能,因为操作系统需要在线程之间来回切换。
3.需要考虑线程操作对程序的影响,如线程挂起,中止等操作对程序的影响。
4.线程使用不当会发生很多问题。
总结:多线程是异步的,但这不代表多线程真的是几个线程是在同时进行,实际上是系统不断地在各个线程之间来回的切换(因为系统切换的速度非常的快,所以给我们在同时运行的错觉)。
2.多线程与高并发的联系。
高并发:高并发指的是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问或者socket端口集中性收到大量请求(例如:12306的抢票情况;天猫双十一活动)。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。如果高并发处理不好,不仅仅降低了用户的体验度(请求响应时间过长),同时可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等。如果要想系统能够适应高并发状态,则需要从各个方面进行系统优化,包括,硬件、网络、系统架构、开发语言的选取、数据结构的运用、算法优化、数据库优化……。
而多线程只是在同/异步角度上解决高并发问题的其中的一个方法手段,是在同一时刻利用计算机闲置资源的一种方式。
多线程在高并发问题中的作用就是充分利用计算机资源,使计算机的资源在每一时刻都能达到最大的利用率,不至于浪费计算机资源使其闲置。
3.线程的创建,停止,常用方法介绍。
1.线程的创建:
线程创建主要有2种方式,一种是继承Thread类,重写run方法即可;(Thread类实现了Runable接口)
另一种则是实现Runable接口,也需要重写run方法。
线程的启动,调用start()方法即可。 我们也可以直接使用线程对象的run方法,不过直接使用,run方法就只是一个普通的方法了。
其他的还有: 通过匿名内部类的方法创建;实现Callable接口。。。。。
2.线程常用方法:
currentThread()方法:该方法返回当前线程的信息 .getName()可以返回线程名称。
isAlive()方法:该方法判断当前线程是否处于活动状态。
sleep()方法:该方法是让“当前正在执行的线程“休眠指定的时间,正在执行的线程是指this.currentThread()返回的线程。
getId()方法:该方法是获取线程的唯一标识。
3.线程的停止:
在java中,停止线程并不简单,不想for。。break那样说停就停,需要一定的技巧。
线程的停止有3种方法:
1.线程正常终止,即run()方法运行结束正常停止。
2.使用interrupt方法中断线程。
3.使用stop方法暴力停止线程。
interrupt方法中断线程介绍:
interrupt方法其实并不是直接中断线程,只是给线程添加一个中断标志。
判断线程是否是停止状态:
this.interrupted(); 判断当前线程是否已经中断。(判断的是这个方法所在的代码对应的线程,而不是调用对象对应的线程)
this.isInterrupted(); 判断线程是否已经中断。(谁调用,判断谁)
注:.interrupted()与isInterrupted()的区别:
interrupted()方法判断的是所在代码对应的线程是否中断,而后者判断的是调用对象对应的线程是否停止
前者执行后有清除状态的功能(如连续调用两次时,第一次返回true,则第二次会返回false)
后者没有清除状态的功能(两次返回都为true)
真正停止线程的方法:
异常法:
在run方法中 使用 this.interrupted();判断线程终止状态,如果为true则 throw new interruptedException()然后捕获该异常即可停止线程。
return停止线程:
在run方法中 使用 this.interrupted();判断线程终止状态,如果为true则return停止线程。 (建议使用异常法停止线程,因为还可以在catch中使线程向上抛,让线程停止的事件得以传播)。
暴力法:
使用stop()方法强行停止线程(强烈不建议使用,会造成很多不可预估的后果,已经被标记为过时)
(使用stop方法会抛出 java.lang.ThreadDeath 异常,并且stop方法会释放锁,很容易造成数据不一致)
注:在休眠中停止线程:
在sleep状态下停止线程 会报异常,并且会清除线程状态值为false;
先停止后sleep,同样会报异常 sleep interrupted;
4.守护线程。
❺ 多线程的定义
在计算机编程中,一个基本的概念就是同时对多个任务加以控制。许多程序设计问题都要求程序能够停下手
头的工作,改为处理其他一些问题,再返回主进程。可以通过多种途径达到这个目的。最开始的时候,那些掌握机器低级语言的程序员编写一些“中断服务例程”,主进程的暂停是通过硬件级的中断实现的。尽管这是一种有用的方法,但编出的程序很难移植,由此造成了另一类的代价高昂问题。中断对那些实时性很强的任务来说是很有必要的。但对于其他许多问题,只要求将问题划分进入独立运行的程序片断中,使整个程序能更迅速地响应用户的请求。
最开始,线程只是用于分配单个处理器的处理时间的一种工具。但假如操作系统本身支持多个处理器,那么每个线程都可分配给一个不同的处理器,真正进入“并行运算”状态。从程序设计语言的角度看,多线程操作最有价值的特性之一就是程序员不必关心到底使用了多少个处理器。程序在逻辑意义上被分割为数个线程;假如机器本身安装了多个处理器,那么程序会运行得更快,毋需作出任何特殊的调校。根据前面的论述,大家可能感觉线程处理非常简单。但必须注意一个问题:共享资源!如果有多个线程同时运行,而且它们试图访问相同的资源,就会遇到一个问题。举个例子来说,两个线程不能将信息同时发送给一台打印机。为解决这个问题,对那些可共享的资源来说(比如打印机),它们在使用期间必须进入锁定状态。所以一个线程可将资源锁定,在完成了它的任务后,再解开(释放)这个锁,使其他线程可以接着使用同样的资源。
多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。
最简单的比喻多线程就像火车的每一节车厢,而进程则是火车。车厢离开火车是无法跑动的,同理火车也不可能只有一节车厢。多线程的出现就是为了提高效率。同时它的出现也带来了一些问题。
❻ 什么是JAVA的多线程
一、 什么是多线程:
我们现在所使用操作系统都是多任务操作系统(早期使用的DOS操作系统为单任务操作系统),多任务操作指在同一时刻可以同时做多件事(可以同时执行多个程序)。
多进程:每个程序都是一个进程,在操作系统中可以同时执行多个程序,多进程的目的是为了有效的使用CPU资源,每开一个进程系统要为该进程分配相关的系统资源(内存资源)
多线程:线程是进程内部比进程更小的执行单元(执行流|程序片段),每个线程完成一个任务,每个进程内部包含了多个线程每个线程做自己的事情,在进程中的所有线程共享该进程的资源;
主线程:在进程中至少存在一个主线程,其他子线程都由主线程开启,主线程不一定在其他线程结束后结束,有可能在其他线程结束前结束。Java中的主线程是main线程,是Java的main函数;
二、 Java中实现多线程的方式:
继承Thread类来实现多线程:
当我们自定义的类继承Thread类后,该类就为一个线程类,该类为一个独立的执行单元,线程代码必须编写在run()方法中,run方法是由Thread类定义,我们自己写的线程类必须重写run方法。
run方法中定义的代码为线程代码,但run方法不能直接调用,如果直接调用并没有开启新的线程而是将run方法交给调用的线程执行
要开启新的线程需要调用Thread类的start()方法,该方法自动开启一个新的线程并自动执行run方法中的内容
java多线程的启动顺序不一定是线程执行的顺序,各个线程之间是抢占CPU资源执行的,所有有可能出现与启动顺序不一致的情况。
CPU的调用策略:
如何使用CPU资源是由操作系统来决定的,但操作系统只能决定CPU的使用策略不能控制实际获得CPU执行权的程序。
线程执行有两种方式:
1.抢占式:
目前PC机中使用最多的一种方式,线程抢占CPU的执行权,当一个线程抢到CPU的资源后并不是一直执行到此线程执行结束,而是执行一个时间片后让出CPU资源,此时同其他线程再次抢占CPU资源获得执行权。
2.轮循式;
每个线程执行固定的时间片后让出CPU资源,以此循环执行每个线程执行相同的时间片后让出CPU资源交给下一个线程执行。
希望对您有所帮助!~
❼ java中如何定义和使用多线程 求例子
有两种,我用了最简单的一种,继承Thread类。模拟迅雷的多线程下载,当你选择下载第一个任务时提示下载需要5秒钟,这时你可以选择同时下载第二个任务。我建了两个类。
第一个类:
public class Multithread extends Thread {
public void run(){
System.out.println("正在下载请等待5秒钟");
try {
Multithread.sleep(5000);
System.out.println(getName()+"下载完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
第二个是测试类:
import java.util.Scanner;
public class Multithreadtest {
public static void main(String[] args) {
System.out.println("1.下载片段a"+"\n2.下载片段b"+"\n3.退出");
Scanner input=new Scanner(System.in);
int choose=0;
while(choose!=3){
System.out.println("请输入你的选择");
choose=input.nextInt();
switch(choose){
case 1: Multithread a=new Multithread();
a.start();
break;
case 2: Multithread b=new Multithread();
b.start();
break;
default :
break;
}
}
System.out.println("程序结束");
}
}
❽ 在Java 中多线程的实现方法有哪些,如何使用
Java多线程的创建及启动
Java中线程的创建常见有如三种基本形式
1.继承Thread类,重写该类的run()方法。
复制代码
1 class MyThread extends Thread {
2
3 private int i = 0;
4
5 @Override
6 public void run() {
7 for (i = 0; i < 100; i++) {
8 System.out.println(Thread.currentThread().getName() + " " + i);
9 }
10 }
11 }
复制代码
复制代码
1 public class ThreadTest {
2
3 public static void main(String[] args) {
4 for (int i = 0; i < 100; i++) {
5 System.out.println(Thread.currentThread().getName() + " " + i);
6 if (i == 30) {
7 Thread myThread1 = new MyThread(); // 创建一个新的线程 myThread1 此线程进入新建状态
8 Thread myThread2 = new MyThread(); // 创建一个新的线程 myThread2 此线程进入新建状态
9 myThread1.start(); // 调用start()方法使得线程进入就绪状态
10 myThread2.start(); // 调用start()方法使得线程进入就绪状态
11 }
12 }
13 }
14 }
复制代码
如上所示,继承Thread类,通过重写run()方法定义了一个新的线程类MyThread,其中run()方法的方法体代表了线程需要完成的任务,称之为线程执行体。当创建此线程类对象时一个新的线程得以创建,并进入到线程新建状态。通过调用线程对象引用的start()方法,使得该线程进入到就绪状态,此时此线程并不一定会马上得以执行,这取决于CPU调度时机。
2.实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。
复制代码
1 class MyRunnable implements Runnable {
2 private int i = 0;
3
4 @Override
5 public void run() {
6 for (i = 0; i < 100; i++) {
7 System.out.println(Thread.currentThread().getName() + " " + i);
8 }
9 }
10 }
复制代码
复制代码
1 public class ThreadTest {
2
3 public static void main(String[] args) {
4 for (int i = 0; i < 100; i++) {
5 System.out.println(Thread.currentThread().getName() + " " + i);
6 if (i == 30) {
7 Runnable myRunnable = new MyRunnable(); // 创建一个Runnable实现类的对象
8 Thread thread1 = new Thread(myRunnable); // 将myRunnable作为Thread target创建新的线程
9 Thread thread2 = new Thread(myRunnable);
10 thread1.start(); // 调用start()方法使得线程进入就绪状态
11 thread2.start();
12 }
13 }
14 }
15 }
复制代码
相信以上两种创建新线程的方式大家都很熟悉了,那么Thread和Runnable之间到底是什么关系呢?我们首先来看一下下面这个例子。
复制代码
1 public class ThreadTest {
2
3 public static void main(String[] args) {
4 for (int i = 0; i < 100; i++) {
5 System.out.println(Thread.currentThread().getName() + " " + i);
6 if (i == 30) {
7 Runnable myRunnable = new MyRunnable();
8 Thread thread = new MyThread(myRunnable);
9 thread.start();
10 }
11 }
12 }
13 }
14
15 class MyRunnable implements Runnable {
16 private int i = 0;
17
18 @Override
19 public void run() {
20 System.out.println("in MyRunnable run");
21 for (i = 0; i < 100; i++) {
22 System.out.println(Thread.currentThread().getName() + " " + i);
23 }
24 }
25 }
26
27 class MyThread extends Thread {
28
29 private int i = 0;
30
31 public MyThread(Runnable runnable){
32 super(runnable);
33 }
34
35 @Override
36 public void run() {
37 System.out.println("in MyThread run");
38 for (i = 0; i < 100; i++) {
39 System.out.println(Thread.currentThread().getName() + " " + i);
40 }
41 }
42 }
复制代码
同样的,与实现Runnable接口创建线程方式相似,不同的地方在于
1 Thread thread = new MyThread(myRunnable);
那么这种方式可以顺利创建出一个新的线程么?答案是肯定的。至于此时的线程执行体到底是MyRunnable接口中的run()方法还是MyThread类中的run()方法呢?通过输出我们知道线程执行体是MyThread类中的run()方法。其实原因很简单,因为Thread类本身也是实现了Runnable接口,而run()方法最先是在Runnable接口中定义的方法。
1 public interface Runnable {
2
3 public abstract void run();
4
5 }
我们看一下Thread类中对Runnable接口中run()方法的实现:
复制代码
@Override
public void run() {
if (target != null) {
target.run();
}
}
复制代码
也就是说,当执行到Thread类中的run()方法时,会首先判断target是否存在,存在则执行target中的run()方法,也就是实现了Runnable接口并重写了run()方法的类中的run()方法。但是上述给到的列子中,由于多态的存在,根本就没有执行到Thread类中的run()方法,而是直接先执行了运行时类型即MyThread类中的run()方法。
3.使用Callable和Future接口创建线程。具体是创建Callable接口的实现类,并实现clall()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程。
看着好像有点复杂,直接来看一个例子就清晰了。
复制代码
1 public class ThreadTest {
2
3 public static void main(String[] args) {
4
5 Callable<Integer> myCallable = new MyCallable(); // 创建MyCallable对象
6 FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); //使用FutureTask来包装MyCallable对象
7
8 for (int i = 0; i < 100; i++) {
9 System.out.println(Thread.currentThread().getName() + " " + i);
10 if (i == 30) {
11 Thread thread = new Thread(ft); //FutureTask对象作为Thread对象的target创建新的线程
12 thread.start(); //线程进入到就绪状态
13 }
14 }
15
16 System.out.println("主线程for循环执行完毕..");
17
18 try {
19 int sum = ft.get(); //取得新创建的新线程中的call()方法返回的结果
20 System.out.println("sum = " + sum);
21 } catch (InterruptedException e) {
22 e.printStackTrace();
23 } catch (ExecutionException e) {
24 e.printStackTrace();
25 }
26
27 }
28 }
29
30
31 class MyCallable implements Callable<Integer> {
32 private int i = 0;
33
34 // 与run()方法不同的是,call()方法具有返回值
35 @Override
36 public Integer call() {
37 int sum = 0;
38 for (; i < 100; i++) {
39 System.out.println(Thread.currentThread().getName() + " " + i);
40 sum += i;
41 }
42 return sum;
43 }
44
45 }
复制代码
首先,我们发现,在实现Callable接口中,此时不再是run()方法了,而是call()方法,此call()方法作为线程执行体,同时还具有返回值!在创建新的线程时,是通过FutureTask来包装MyCallable对象,同时作为了Thread对象的target。那么看下FutureTask类的定义:
1 public class FutureTask<V> implements RunnableFuture<V> {
2
3 //....
4
5 }
1 public interface RunnableFuture<V> extends Runnable, Future<V> {
2
3 void run();
4
5 }
于是,我们发现FutureTask类实际上是同时实现了Runnable和Future接口,由此才使得其具有Future和Runnable双重特性。通过Runnable特性,可以作为Thread对象的target,而Future特性,使得其可以取得新创建线程中的call()方法的返回值。
执行下此程序,我们发现sum = 4950永远都是最后输出的。而“主线程for循环执行完毕..”则很可能是在子线程循环中间输出。由CPU的线程调度机制,我们知道,“主线程for循环执行完毕..”的输出时机是没有任何问题的,那么为什么sum =4950会永远最后输出呢?
原因在于通过ft.get()方法获取子线程call()方法的返回值时,当子线程此方法还未执行完毕,ft.get()方法会一直阻塞,直到call()方法执行完毕才能取到返回值。
上述主要讲解了三种常见的线程创建方式,对于线程的启动而言,都是调用线程对象的start()方法,需要特别注意的是:不能对同一线程对象两次调用start()方法。
你好,本题已解答,如果满意
请点右下角“采纳答案”。