java月薪20k需要什么,关于java:这几种实现线程的方法你一定要知道月薪20k以上的面试都会问到...

实现线程的三种形式总结

最近有看到Java线程的实现相干问题,在此对线程实现形式做一个小小的总结,当做笔记,便于日后查看。

平时罕用的线程形式有三种:

(1)、继承Thread类,并重写其run()办法。

(2)、实现Runnable接口,并实现其run()办法。

(3)、实现Callable接口,并实现其call()办法。

一、继承Thread类

Thread 类中创立线程最重要的两个办法为:

public void start();

public void run();

采纳 Thread 类创立线程,用户只须要继承 Thread,笼罩 Thread 中的 run 办法,父类 Thread 中的 run 办法没有抛出异样,那么子类也不能抛出异样,最初采纳 start 启动线程即可。

【示例代码1】不应用线程

public class ThreadTest01 {

public static void main(String[] args) {

Processor p = new Processor();

p.run();

method1();

}

private static void method1() {

System.out.println("--------method1()----------");

}

}

class Processor {

public void run() {

for (int i=0; i<10; i++) {

System.out.println(i);

}

}

}

【执行后果】

0

1

2

3

4

5

6

7

8

9

--------method1()----------

以上程序输入相应的后果(属于串行) , 也就是 run 办法齐全执行实现后,才执行 method1 办法, 也就是 method1 必须期待后面的办法返回才能够失去执行,这是一种“同步编程模型”。

这样执行存在什么样的弊病呢?

依照程序执行,这就极大的升高了程序的执行效率。无奈同时执行多个代码片段,这也是多线程并发所要达到的目标。

【示例代码2】应用线程

public class ThreadTest02 {

public static void main(String[] args) {

Processor p = new Processor();

/*

如果是手动调用该办法,

则并不能采纳 run 来启动一个场景(线程),

run 就是一个一般办法调用。

*/

//p.run();

/*

采纳 start 启动线程,不是间接调用 run,

start 不是马上执行线程,而是使线程进入就绪状态

线程的真正执行是由 Java 的线程调度机制实现的。

*/

p.start();

//线程只能启动一次,无奈启动屡次

//p.start();

method1();

}

private static void method1() {

System.out.println("--------method1()----------");

}

}

class Processor extends Thread {

/*

笼罩 Thread 中的 run 办法,该办法没有异样

该办法是由 java 线程调度机制调用的,因而

咱们不应该手动调用该办法

*/

public void run() {

for (int i=0; i<10; i++) {

System.out.println(i);

}

}

}

【执行后果】

--------method1()----------

0

1

2

3

4

5

6

7

8

9

通过输入后果大家会看到,没有依照程序执行,而在输入数字的同时执行了 method1()办法,如果从效率上看,采纳多线程的示例要快些,因为咱们能够看作他是同时执行的, mthod1()办法没有期待后面的操作实现才执行, 这叫“异步编程模型”。

那么,为什么会是这样的执行后果呢?

这就波及到Java线程的调度机制了,该程序蕴含两个线程一个是主线程也就是main线程,另外一个是用户创立的p线程,当类加载实现后,主线程启动,开始执行main办法栈帧,依照代码自上而下的执行程序,先创立Processor的实例化对象p,接着是执行p.start();启动p线程,这时method1();办法还没有执行,此时两个线程均曾经启动,依照Java线程调度的规定,两个线程开始争夺执行程序的工夫片(即CPU的执行权),留神,这种争夺是随机的,也就是说,不肯定输入后果就是method1办法先执行,for循环语句后执行。能够多执行几次即可看到不一样的执行后果。

二、实现 Runnable 接口

其实 Thread 对象自身就实现了 Runnable 接口,但个别倡议间接应用 Runnable 接口来写多线程程序,因为接口会比类带来更多的益处(面向接口编程的准则)。

【示例代码3】

public class ThreadTest03 {

public static void main(String[] args) {

//Processor r1 = new Processor();

/*

应用多态机制父类型援用指向子类型对象,

因为这样能够调用Runnable接口的办法

*/

Runnable r1 = new Processor();

//不能间接调用 run办法,起因见上文

//p.run();

//创立线程对象,并将r1对象作为参数传入(Thread的构造方法)

Thread t1 = new Thread(r1);

//启动线程

t1.start();

method1();

}

private static void method1() {

System.out.println("--------method1()----------");

}

}

//实现 Runnable 接口

class Processor implements Runnable {

//实现 Runnable 中的 run 办法

public void run() {

for (int i=0; i<10; i++) {

System.out.println(i);

}

}

}

【执行后果】

--------method1()----------

0

1

2

3

4

5

6

7

8

9

后果剖析见上,起因是一样的,只不过是换了一种形式实现线程而已。

三、实现Callable接口

察看上文两种线程的执行形式,存在什么毛病。显然,以上两种线程的执行un办法时是没有返回值的,而实际上也会存在须要失去线程执行的返回后果的状况,那么怎么办呢?这时就能够思考应用第三种线程的实现形式。

长处:能够获取到线程的执行后果。

毛病:效率比拟低,在获取t线程执行后果的时候,以后线程受阻塞,效率较低。

【示例代码4-1】应用匿名外部类

import java.util.concurrent.Callable;

import java.util.concurrent.FutureTask;

public class ThreadTest04 {

public static void main(String[] args) throws Exception {

// 第一步:创立一个“将来工作类”对象。

// 参数十分重要,须要给一个Callable接口实现类对象。

FutureTask task = new FutureTask(new Callable() {

@Override

public Object call() throws Exception { // call()办法就相当于run办法。只不过这个有返回值

// 线程执行一个工作,执行之后可能会有一个执行后果

// 模仿执行

System.out.println("call method begin");

Thread.sleep(1000 * 10);//以后线程睡眠10秒

System.out.println("call method end!");

int a = 100;

int b = 200;

return a + b; //主动装箱(300后果变成Integer)

}

});

// 创立线程对象

Thread t = new Thread(task);

// 启动线程

t.start();

// 这里是main办法,这是在主线程中。

// 在主线程中,怎么获取t线程的返回后果?

// get()办法的执行会导致“以后线程阻塞”

Object obj = task.get();

System.out.println("线程执行后果:" + obj);

// main办法这里的程序要想执行必须期待get()办法的完结

// 而get()办法可能须要很久。因为get()办法是为了拿另一个线程的执行后果

// 另一个线程执行是须要工夫的。

System.out.println("hello world!");

}

}

【执行后果】

call method begin

call method end!

线程执行后果:300

hello world!

【示例代码4-2】不应用匿名外部类

import java.util.concurrent.Callable;

import java.util.concurrent.FutureTask;

public class ThreadTest01 {

public static void main(String[] args) throws Exception {

//创立Callable接口的实现类的实例化对象

CallableImpl callable = new CallableImpl();

// 第一步:创立一个“将来工作类”对象。

// 参数十分重要,须要给一个Callable接口实现类对象。

FutureTask task = new FutureTask(callable);

// 创立线程对象

Thread t = new Thread(task);

// 启动线程

t.start();

// 这里是main办法,这是在主线程中。

// 在主线程中,怎么获取t线程的返回后果?

// get()办法的执行会导致“以后线程阻塞”

Object obj = task.get();

System.out.println("线程执行后果:" + obj);

// main办法这里的程序要想执行必须期待get()办法的完结

// 而get()办法可能须要很久。因为get()办法是为了拿另一个线程的执行后果

// 另一个线程执行是须要工夫的。

System.out.println("hello world!");

}

}

//实现Callable接口

class CallableImpl implements Callable{

@Override

public Object call() throws Exception { // call()办法就相当于run办法。只不过这个有返回值

// 线程执行一个工作,执行之后可能会有一个执行后果

// 模仿执行

System.out.println("call method begin");

Thread.sleep(1000 * 10);//以后线程睡眠10秒

System.out.println("call method end!");

int a = 100;

int b = 200;

return a + b; //主动装箱(300后果变成Integer)

}

}

【执行后果】

call method begin

call method end!

线程执行后果:300

hello world!

最初

谢谢你的观看,感觉文章对你有帮忙的话记得关注我点个赞反对一下!也欢送大家关注我的公众号:前程有光,金三银四跳槽面试季,整顿了1000多道将近500多页pdf文档的Java面试题材料,每天都会分享java相干技术文章或行业资讯,整顿的材料也会放在外面。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值