多线程的理解
可以理解成进程中独立运行的子任务,比如QQ.exe运行时的视频聊天线程,下载文件线程,发送表情线程等,这些不同的任务或功能可以“同时”运行。实际上,CPU在这些线程之间不断的切换,这样做可以最大限度的利用CPU的空闲时间。
Java多线程的创建和使用
java中的main是一个独立的线程,对于多线程,我们主要使用三种方法创建和使用:
- 继承Thread类,重写run(),实例化并使用
- 实现Runnable接口,重写run(),作为Thread的Target,实例化并使用
- 实现Callable接口,FutureTask包装类作为Thread的Target,实例化并使用
1)继承Thread类,重写run()方法
写一个最简单的例子实现多线程,创建class MyThread继承Thread类,并且
重写run(),方法体输出文本。
在main中实例化并调用start()进入RUNNABLE状态听候CPU调用run(),
此时即实现了多线程!
public class B{
public static void main(String[] args){
MyThread mtd = new MyThread();
mtd.start();
System.out.println("operation done");
}
}
class MyThread extends Thread{
@Override
public void run(){
System.out.println("MyThread");
}
}
输出:
operation done
MyThread
or
MyThread
operation done
上述代码每次执行结果不一定相同,也说明了多线程之间的任务完成次序并不像
单线程多个任务那样线性。
2) 实现Runnable,重写run(),作为Thread的target成员变量
接下来看Runnable,这里调用的是Thread(Runnable target)这个构造器,
等同于调用Thread(null,target,gname),gname代表默认自动生成的线程名“Thread-”+n,当构造参数target不为null时,该Thread运行时执行target.run(),否则将不做任何事。
public class B{
public static void main(String[] args){
MyRunnable myRunnable = new MyRunnable();
Thread myThread = new Thread(myRunnable);
myThread.start();
}
}
class MyRunnable implements Runnable{
@Override
public void run(){
System.out.println("My Runnable thread running");
}
}
输出:
My Runnable thread running
给建立的Thread取名
利用Thread类中 Thread(“String name”) 构造法可以覆盖默认的其默认方法中的“Thread-”+n
相当于调用 Thread(null,null,name)
public class B{
public static void main(String[] args){
MyRunnable myRunnable = new MyRunnable();
Thread myThread1 = new MyThread("Thread Dark");
Thread myThread2 = new MyThread(myRunnable,"Thread Light");
myThread1.start();
myThread2.start();
}
}
class MyThread extends Thread{
public MyThread(Runnable myRunnable,String name){
super(myRunnable,name);
}
public MyThread(String name){
super(name);
}
@Override
public void run(){
super.run();
System.out.println("my subthread running "+ Thread.currentThread().getName());
}
}
class MyRunnable implements Runnable{
@Override
public void run(){
System.out.println("runnable thread running"+Thread.currentThread().getName());
}
}
输出
runnable thread runningThread Light
my subthread running Thread Light
my subthread running Thread Dark
这里看到Thread Light调用了Runnable实现类MyRunnable中的run()方法,
Thread Dark由于target = null,所以super.run()将不执行线程任何任务。
3)实现Callable接口,用FutureTask类包装,作为Thread target成员实例化线程
Interface Callable<T>
是一个T call() throws Exception
功能接口,功能类似Runnable,但是call()比run()多了返回类型T和抛出异常的规则设定。
Class FutureTask<T>
是一个实现了RunnableFuture<T>
的类,成员变量有Callable callable,Runnable runnable,和T result
主要有public FutureTask(Callable<T> callable)
和public FutureTask(Runnable runnable,T result)
两种构造法。
import java.math.*;
import java.util.*;
import java.util.concurrent.*;
public class B{
public static void main(String[] args){
MyCallable myCallable = new MyCallable();
FutureTask<Integer> ft = new FutureTask<Integer>(myCallable);
Thread myThread3 = new Thread(ft,"Thread Future");
myThread3.start();
try{
int sum = ft.get();
System.out.println("1+2+3+...+10= " + sum);
}catch(Exception e){
e.printStackTrace();
}
}
}
class MyCallable implements Callable<Integer>{
private int i = 0;
@Override
public Integer call(){
int sum = 0;
System.out.println("callable thread running: "+Thread.currentThread().getName());
while (i<11){
sum+=i++;
}
return sum;
}
}
输出结果
callable thread running: Thread Future
1+2+3+...+10= 55