Java多线程系列(1)--实现多线程的三种方式

今天,就开始学习多线程的知识。
首先我们先对多线程有个基本了解,然后进行比较的理解与学习。

一、多线程的相关概念

image
由上面的框图可以得到,线程共包括下面5种状态。
(1)新建状态(new):线程被对象创建后,就进入了新建状态。例:Thread thread = new Thread();
(2)就绪状态(Runnable):也被成为“可执行状态”。线程被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例:threa.start();处于就绪状态的线程,随时可能被CPU调度执行;
(3)运行状态(Running):线程获取CPU权限进行执行,需要注意的是,线程只能从就绪状态进入到运行状态;
(4)阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞情况分为三种:
a、等待阻塞:通过线程的wait()方法,让线程等待某工作的完成。
b、同步阻塞:线程在获取synchronized同步锁失败(因为锁被其它线程所占用),会进入同步阻塞状态。
c、其它阻塞:通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
(5)死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

二、Thread类、Runnable接口、Callable接口的简介

(1)Runnable是一个接口,该接口中只包含了一个run()方法。定义如下:

public interface Runnable {
    public abstract void run();
}

Runnable是实现多线程,我们可以定义一个类A实现了Runnable接口,然后通过new Thread(new A())来新建线程;
(2)Thread是一个类,本省就实现了Runnable接口,声明如下:

public class Thread implements Runnable {}

Thread的作用就是实现多线程。
(3)实现Callable接口,重写call函数,Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。
补充:Thread是类,而Runnable是接口;Thread本身实现了Runnable接口的类。我们知道,一个类只能有一个父类,但是却能实现多个接口,因此,Runnable具有更好的扩展性。
除此之外,Runnable还可以用于资源的共享,即多个线程都是基于一个Runnable对象建立的,它们会共享Runnabled对象上的资源,一般建议使用Runnable实现多线程。

三、实现多线程的三种方式:分别是继承Thread类、实现Runnable接口、实现Callable接口,重写call函数

(1)继承Thread类,代码实例如下:

package Test;

/**
 * Created by LKL on 2017/2/20.
 */
public class MyThread extends Thread{
        private int ticket=20;
       //重写run方法
        public void run(){
            for (int i=0;i<20;i++){
                if(this.ticket>0){
                    System.out.println(this.getName()+"卖票:ticket"+this.ticket--);
                }
            }
        }
}

package Test;

/**
 * Created by LKL on 2017/2/20.
 */
public class MyThread extends Thread{
        private int ticket=20;
       //重写run方法
        public void run(){
            for (int i=0;i<20;i++){
                if(this.ticket>0){
                    System.out.println(this.getName()+"卖票:ticket"+this.ticket--);
                }
            }
        }
}

运行结果如下:

Thread-0卖票:ticket20
Thread-0卖票:ticket19
Thread-0卖票:ticket18
Thread-0卖票:ticket17
Thread-0卖票:ticket16
Thread-0卖票:ticket15
Thread-0卖票:ticket14
Thread-0卖票:ticket13
Thread-0卖票:ticket12
Thread-0卖票:ticket11
Thread-0卖票:ticket10
Thread-0卖票:ticket9
Thread-0卖票:ticket8
Thread-0卖票:ticket7
Thread-0卖票:ticket6
Thread-0卖票:ticket5
Thread-0卖票:ticket4
Thread-0卖票:ticket3
Thread-0卖票:ticket2
Thread-0卖票:ticket1
Thread-1卖票:ticket20
Thread-1卖票:ticket19
Thread-1卖票:ticket18
Thread-1卖票:ticket17
Thread-1卖票:ticket16
Thread-1卖票:ticket15
Thread-1卖票:ticket14
Thread-1卖票:ticket13
Thread-1卖票:ticket12
Thread-1卖票:ticket11
Thread-1卖票:ticket10
Thread-1卖票:ticket9
Thread-1卖票:ticket8
Thread-2卖票:ticket20
Thread-2卖票:ticket19
Thread-2卖票:ticket18
Thread-1卖票:ticket7
Thread-2卖票:ticket17
Thread-1卖票:ticket6
Thread-2卖票:ticket16
Thread-2卖票:ticket15
Thread-2卖票:ticket14
Thread-2卖票:ticket13
Thread-1卖票:ticket5
Thread-2卖票:ticket12
Thread-3卖票:ticket20
Thread-2卖票:ticket11
Thread-1卖票:ticket4
Thread-2卖票:ticket10
Thread-3卖票:ticket19
Thread-2卖票:ticket9
Thread-1卖票:ticket3
Thread-2卖票:ticket8
Thread-3卖票:ticket18
Thread-2卖票:ticket7
Thread-1卖票:ticket2
Thread-2卖票:ticket6
Thread-2卖票:ticket5
Thread-3卖票:ticket17
Thread-2卖票:ticket4
Thread-1卖票:ticket1
Thread-2卖票:ticket3
Thread-2卖票:ticket2
Thread-3卖票:ticket16
Thread-2卖票:ticket1
Thread-3卖票:ticket15
Thread-3卖票:ticket14
Thread-3卖票:ticket13
Thread-3卖票:ticket12
Thread-3卖票:ticket11
Thread-3卖票:ticket10
Thread-3卖票:ticket9
Thread-3卖票:ticket8
Thread-3卖票:ticket7
Thread-3卖票:ticket6
Thread-3卖票:ticket5
Thread-3卖票:ticket4
Thread-3卖票:ticket3
Thread-3卖票:ticket2
Thread-3卖票:ticket1

由上述结果说明:
1>Mythread继承于Thread类,它是自定义的线程,每个MyThread都会卖票;
2>主线程Main创建并启动4个子线程,每个子线程都会卖出20张票。
(2)实现Runnable接口,代码实例如下:

package Test;

/**
 * Created by LKL on 2017/2/20.
 */
public class TestRunnable {
    public static void main(String[] args){
        MyThread1 thread = new MyThread1();
        //启动四个线程t1、t2、t3、t4(他们共用一个线程),这四个线程一共买【卖票20张
        Thread t1 = new Thread(thread);
        Thread t2 = new Thread(thread);
        Thread t3 = new Thread(thread);
        Thread t4 = new Thread(thread);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

package Test;

/**
 * Created by LKL on 2017/2/20.
 */
public class MyThread1 implements Runnable{
    private int ticket=50;
    public void run(){
        for(int i=0;i<50;i++){
            if(this.ticket>0){
                System.out.println(Thread.currentThread().getName()+"卖票:ticket"+this.ticket--);
            }
        }
    }
}

运行结果如下:

Thread-0卖票:ticket50
Thread-0卖票:ticket49
Thread-0卖票:ticket48
Thread-0卖票:ticket47
Thread-0卖票:ticket46
Thread-0卖票:ticket45
Thread-0卖票:ticket44
Thread-0卖票:ticket43
Thread-0卖票:ticket42
Thread-1卖票:ticket41
Thread-0卖票:ticket40
Thread-1卖票:ticket39
Thread-1卖票:ticket37
Thread-1卖票:ticket36
Thread-1卖票:ticket35
Thread-1卖票:ticket34
Thread-1卖票:ticket33
Thread-1卖票:ticket32
Thread-1卖票:ticket31
Thread-1卖票:ticket30
Thread-1卖票:ticket29
Thread-1卖票:ticket28
Thread-1卖票:ticket27
Thread-1卖票:ticket26
Thread-1卖票:ticket25
Thread-0卖票:ticket38
Thread-0卖票:ticket23
Thread-1卖票:ticket24
Thread-1卖票:ticket21
Thread-0卖票:ticket22
Thread-1卖票:ticket20
Thread-0卖票:ticket19
Thread-2卖票:ticket17
Thread-1卖票:ticket18
Thread-1卖票:ticket14
Thread-1卖票:ticket13
Thread-1卖票:ticket11
Thread-1卖票:ticket10
Thread-1卖票:ticket9
Thread-1卖票:ticket8
Thread-1卖票:ticket7
Thread-1卖票:ticket6
Thread-2卖票:ticket15
Thread-2卖票:ticket4
Thread-0卖票:ticket16
Thread-2卖票:ticket3
Thread-1卖票:ticket5
Thread-3卖票:ticket12
Thread-2卖票:ticket1
Thread-0卖票:ticket2

有上述代码可以得到:
此时MyThread1实现了Runnable接口;主线程main创建并启动了4个线程,而且这四个线程都是基于thread这个Runnable对象创建的,运行结果是这四个线程共卖出了50张票,它们是共享了MyRhread1接口的。
(3)实现Callable接口,重写call函数,带有返回值的(同时还有ExecutorService、Future ),启动后主线程可以根据线程对象来判断显示是否结束以及获取线程执行结果,多用于执行主任务时需要执行一个耗时的辅助任务,但是主任务的执行结果或者执行结果依赖于辅助任务的执行结果,代码实例如下:

package Test;

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * Created by LKL on 2017/2/20.
 */
public class TestCallable {
    public static void main(String[] args) throws InterruptedException,
            ExecutionException {
        ExecutorService exec = Executors.newCachedThreadPool();
        ArrayList<Future<String>> results = new ArrayList<Future<String>>();    //Future 相当于是用来存放Executor执行的结果的一种容器
        for (int i = 0; i < 100; i++) {
            results.add(exec.submit(new TaskCallable(i)));
        }
        for (Future<String> fs : results) {
            if (fs.isDone()) {
                System.out.println(fs.get());
            } else {
                System.out.println("Future result is not yet complete");
            }
        }
        exec.shutdown();
    }
}

package Test;

import java.util.concurrent.Callable;

/**
 * Created by LKL on 2017/2/20.
 */
public class TaskCallable implements Callable<String>{
    private int id;

    public TaskCallable(int id) {
        this.id = id;
    }

    @Override
    public String call() throws Exception {
        return "result of TaskCallable " + id;
    }

}

运行结果如下:

result of TaskCallable 0
result of TaskCallable 1
result of TaskCallable 2
result of TaskCallable 3
result of TaskCallable 4
result of TaskCallable 5
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
result of TaskCallable 43
result of TaskCallable 44
Future result is not yet complete
result of TaskCallable 46
result of TaskCallable 47
Future result is not yet complete
result of TaskCallable 49
result of TaskCallable 50
Future result is not yet complete
Future result is not yet complete
result of TaskCallable 53
result of TaskCallable 54
Future result is not yet complete
result of TaskCallable 56
result of TaskCallable 57
Future result is not yet complete
Future result is not yet complete
Future result is not yet complete
result of TaskCallable 61
Future result is not yet complete
Future result is not yet complete
result of TaskCallable 64
Future result is not yet complete
result of TaskCallable 66
Future result is not yet complete
result of TaskCallable 68
Future result is not yet complete
result of TaskCallable 70
result of TaskCallable 71
result of TaskCallable 72
result of TaskCallable 73
result of TaskCallable 74
result of TaskCallable 75
result of TaskCallable 76
result of TaskCallable 77
result of TaskCallable 78
result of TaskCallable 79
Future result is not yet complete
result of TaskCallable 81
result of TaskCallable 82
result of TaskCallable 83
result of TaskCallable 84
Future result is not yet complete
result of TaskCallable 86
result of TaskCallable 87
result of TaskCallable 88
result of TaskCallable 89
result of TaskCallable 90
result of TaskCallable 91
result of TaskCallable 92
result of TaskCallable 93
result of TaskCallable 94
result of TaskCallable 95
result of TaskCallable 96
result of TaskCallable 97
result of TaskCallable 98
Future result is not yet complete

submit()方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化。可以用isDone()方法来查询Future是否已经完成。当任务完成时,它具有一个结果,你可以调用get()方法来获取该结果。你也可以不使用isDone()方法进行检查就直接调用get(),在这种情况下,get()将阻塞,直至结果准备就绪。也可以在试图调用get()来获取结果之前,先调用具有超时的get(),或者调用isDone()来查看任务是否完成。

文章只是作为自己的学习笔记,借鉴了网上的许多案例,如果觉得阔以的话,希望多交流,在此谢过…

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值