Java实现多线程的方法

Java实现多线程主要包括三种方式:
 继承Thread类
 实现Runnable接口
 实现Callable接口
区别:
1.继承Thread类和实现Runnable方法启动线程都是使用start方法,然后JVM将此线程放到就绪队列,如果有处理机可用,则执行run方法。
2.实现Callable接口要实现call方法,并且线程执行完毕后会有返回值,其他两种重写run方法,没有返回值。
3.call()方法可抛出异常,而run()方法是不能抛出异常的。
4.实现Runnable和Callable接口还可以集成其他类,而继承Thread后不能再继承其他类
5.实现Runnable和Callable接口如果要访问当前线程,必须使用Thread.currentThread(),继承Thread类直接使用this即可获得当前线程、

1.Thread 类

class NewThread extends Thread{
    public NewThread() {
        // TODO Auto-generated constructor stub
        System.out.println("创建子线程"+this);
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        try{
            for(int i = 0;i<5;i++){
                System.out.println("子线程->"+i);
                this.sleep(100);
            }
        }catch (Exception e) {
            // TODO: handle exception
        }
        System.out.println("退出子线程");
    }
}
public class ThreadDemo{

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        NewThread newThread = new NewThread();
        newThread.start();//启动子线程
        System.out.println("主线程");
        try{
            for(int i = 0;i<5;i++){
                System.out.println("主线程->"+i);
                Thread.sleep(50);
            }
        }catch (Exception e) {
            // TODO: handle exception
        }
        System.out.println("退出主线程");
    }

}

运行结果:
这里写图片描述
上述代码可以看出,主线程设置的睡眠时间小于子线程,因此,主线程先于主线程完成,主线程退出后,子线程继续完成。主线程结束后,也可以调用stop方法结束子线程。也可以调用System.exit(0);强制退出进程。
这里写图片描述
2.Runnable接口
这里采用think in Java的例子。

class LifftOff implements Runnable{
    protected int countdown = 10;
    private static int taskCount = 0;
    private final int id = taskCount++;
    public LifftOff() {
        // TODO Auto-generated constructor stub
    }
    public LifftOff(int countdown) {
        this.countdown = countdown;
    }
    public String status(){
        return "#"+id+"("+countdown+")";
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(countdown-->0){
            System.out.print(status());
            Thread.yield();//对线程调度器的一种建议,声明“我已经完成生命周期中最重要的组成部分了,此刻正是切换给其他任务执行一段时间的大好时机”
        }
    }   
}

public class RunableDemo {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        LifftOff lifftOff = new LifftOff();
        lifftOff.run();
    }

}

结果为:
这里写图片描述
将Runnable对象转变为工作任务的传统方式是把它提交给一个Thread构造器,下面用实例展示Thread来驱动LiftOff对象。

public class RunableDemo {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        for(int i = 0;i<5;i++){
            new Thread(new LifftOff()).start();
        }
    }
}

结果为:
这里写图片描述
由实验结果可以看出,不同任务的执行在线程换进换出时混在一起,这种线程交换是由线程调度器控制的,如果机器上有多个处理器,线程调度器将会在这些处理器之间默默分发线程。

3.Callable接口

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

class Calltest implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        // TODO Auto-generated method stub
        int sum = 0;
        for(int i = 1;i<1000;i++){
            sum = sum + i;
        }
        return sum;
    }   
}
public class CallableDemo {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Calltest calltest = new Calltest();
        //Callable方式需要FutureTask实现类的支持,用于接收运算结果
        FutureTask<Integer> result = new FutureTask<Integer>(calltest);
        new Thread(result).start();
        try{
            System.out.println(result.isDone());
            Integer sum = result.get();//获取任务执行结果,如果任务未完成则阻塞等待直到任务完成
            System.out.println(sum);
            System.out.println(result.isDone());        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }

}

结果为
这里写图片描述
FutrueTask(源自www.importnew.com/25286.html):
Future接口代表异步计算的结果,通过Future接口提供的方法可以查看异步计算是否执行完成,或者等待执行结果并获取执行结果,同时还可以取消执行。

  • cancel():cancel()方法用来取消异步任务的执行。如果异步任务已经完成或者已经被取消,或者由于某些原因不能取消,则会返回false。如果任务还没有被执行,则会返回true并且异步任务不会被执行。如果任务已经开始执行了但是还没有执行完成,若mayInterruptIfRunning为true,则会立即中断执行任务的线程并返回true,若mayInterruptIfRunning为false,则会返回true且不会中断任务执行线程。
  • isCanceled():判断任务是否被取消,如果任务在结束(正常执行结束或者执行异常结束)前被取消则返回true,否则返回false。
  • isDone():判断任务是否已经完成,如果完成则返回true,否则返回false。需要注意的是:任务执行过程中发生异常、任务被取消也属于任务已完成,也会返回true
  • get():获取任务执行结果,如果任务还没完成则会阻塞等待直到任务执行完成。如果任务被取消则会抛出CancellationException异常,如果任务执行过程发生异常则会抛出ExecutionException异常,如果阻塞等待过程中被中断则会抛出InterruptedException异常。
  • get(long timeout,Timeunit unit):带超时时间的get()版本,如果阻塞等待过程中超时则会抛出TimeoutException异常。

关于多线程中的Join
主要作用:同步,可以使得线程之间的并行执行变为串行执行。
如在上述的ThreadDemo中做出修改:

public class ThreadDemo{

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        NewThread newThread = new NewThread();
        newThread.start();//启动子线程
        System.out.println("主线程");
        newThread.join();
        try{
            for(int i = 0;i<5;i++){
                System.out.println("主线程->"+i);
                Thread.sleep(50);
            }
        }catch (Exception e) {
            // TODO: handle exception
        }
        System.out.println("退出主线程");
        System.exit(0);
    }

}

结果为:
这里写图片描述
Join的意思是放弃当前线程的执行,并返回相应的线程。
程序在Main线程中调用newThread线程的join方法,则main线程放弃CPU控制权,并返回newThread线程继续执行直到newThread执行完毕。因此直到newThread结束才返回主线程执行。
上述内容部分来源于网络和书本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值