在java中多线程有以下四种方法:
一、继承Thread类实现多线程
继承Thread类并且覆写run()方法来实现多线程,继承Thread类需要需要注意一个线程只能调用一次start()方法。
如以下代码:
class Mythread extends Thread{
private String title;
public Mythread(String title){
this.title=title;
}
public void run(){
for(int i=0;i<10;i++){
System.out.println(this.title+",i= "+i);
}
}
}
public class Test {
public static void main(String[] args) {
Mythread thread1=new Mythread("线程1");
Mythread thread2=new Mythread("线程2");
Mythread thread3=new Mythread("线程3");
thread1.start();
thread2.start();
thread3.start();
}
}
由于Thread是一个类,因此会有多继承局限,因此引入了一个接口Runnable()接口来实现多线程
二、继承Runnable()接口来实现多线程
继承Runnable()实现多线程由代码所示:
package Runnable;
class Mythread implements Runnable{
private String title;
public Mythread(String title){
this.title=title;
}
public void run() {
for(int i=0;i<10;i++){
System.out.println(this.title+",i= "+i);
}
}
}
public class Test {
public static void main(String[] args) {
Mythread thread1=new Mythread("线程1");
Mythread thread2=new Mythread("线程2");
Mythread thread3=new Mythread("线程3");
new Thread(thread1).start();
new Thread(thread2).start();
new Thread(thread3).start();
}
}
由于Runnable()接口中没有提供start()方法来启动多线程,因此我们在产生实例化对象时需要借助于Thread()提供的start()
方法来启动多线程。
使用Runnable和Thread来实现多线程有以下两种主要的区别:
1.Runnable实现多线程时,可以避免多线程局限。
2.使用Runnable实现多线程的程序类可以更好的描述出程序共享的概念。 当然并不是说Thread不能。
三、Callable实现多线程
import java.util.concurrent.FutureTask;
class Mythread implements Callable<String>{
private int ticket=10;
public String call() throws Exception {
while(this.ticket>0){
System.out.println("剩余票数:"+this.ticket--);
}
return "票卖完了";
}
}
public class Test {
public static void main(String[] args) throws InterruptedException, ExecutionException
{
FutureTask<String> task=new FutureTask<String>(new Mythread());
new Thread(task).start();
new Thread(task,"线程1").start();
System.out.println(task.get());
}
}
我们可以观察到Callable也是一个接口,它与Runnable()差别主要是在:
- Callable规定的方法是call(),而Runnable规定的方法是run().
- Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
- call()方法可抛出异常,而run()方法是不能抛出异常的。
- 运行Callable任务可拿到一个Future对象, Future表示异步计算的结果。
- 通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。
四、ExecutorService、Callable、Future实现有返回结果的多线程
public class test {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(5);
// newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
// newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
// newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
// newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
List<Future> futureList= new ArrayList<Future>();
for (int i = 0; i <5; i++) {
Callable task = new TestCallable("wq"+i, "phone"+i);
Future<Object> f = threadPool.submit(task);
futureList.add(f);
}
threadPool.shutdown();
for (Future future : futureList) {
try {
System.out.println(future.get().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class TestCallable implements Callable<Object>{
private String name;
private String phone;
TestCallable(String name,String phone){
this.name=name;
this.phone=phone;
}
public Object call() throws Exception {
System.out.println(name+"----"+phone);
return name+"--return--"+phone;
}
}
Java中多线程的方法有多种多样,每种方法也各有优劣,在不同的环境下,最好能灵活的选用不同的调用方法。