java 线程 --- Thread,Runnable,Callable 基础学习(2)

            //获取当前的线程,只能用 Thread.currentThread() 获取当前的线程名

            Log.d(TAG,Thread.currentThread().getName()+" "+i);



            if(this.ticket>0){

                Log.e(TAG, Thread.currentThread().getName() + ", 卖票:ticket=" + ticket--);

            }

        }

    }

}





private void starTicketThread2(){

    Log.d(TAG,"starTicketThread2, "+Thread.currentThread().getName());



    SecondThread secondThread = new SecondThread();



    //通过new Thread(target,name)创建新的线程

    new Thread(secondThread,"买票人1").start();

    new Thread(secondThread,"买票人2").start();

    new Thread(secondThread,"买票人3").start();



    //虽然是开启了3个线程,但是一共只买了100张票

}



运行结果:



![这里写图片描述](https://img-blog.csdn.net/20161221161003902?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZF9mcmVzaG1hbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)



> 可以看到 3 个线程输入的 票数变量是连续的,采用 Runnable 接口的方式创建多个线程可以共享线程类的实例的属性。这是因为在这种方式下,程序所创建的Runnable 对象只是线程的 target ,而多个线程可以共享同一个 target,所以多个线程可以共享同一个线程类(实际上应该是该线程的target 类)的实例属性。



* * *



#### **3.使用 Callable 和Future 创建线程**



从 java 5 开始,Java 提供了 Callable 接口,该接口是runnable 的增强版,Callable 提供类一个 call() 方法可以作为线程执行体,但是call() 方法的功能更强大。  

(1) call() 方法可以有返回值  

(2) call() 方法可以声明抛出异常



因此我们完全可以提供一个callable 对象作为Thread的 target ,而该线程的执行体就是该callable 对象的call() 方法。同时 java 5 提供了 Future 接口 来代表Callable 接口里 call() 方法的返回值,并且提供了一个 futureTask 的实现类,该实现类实现类 future 接口,并实现了runnable 接口—可以作为Thread 类的target.



**启动步骤如下:**  

(1)创建callable接口的实现类,并实现call() 方法,该call() 方法将作为线程的执行体,且该call() 方法是有返回值的。  

(2)创建 callable实现类的实例,使用 FutureTask 类来包装Callable对象,该FutureTask 对象封装 call() 方法的返回值。  

(3)使用FutureTask 对象作为Thread对象的target创建并启动新线程。  

(4)调用FutureTask对象的get()方法来获取子线程执行结束后的返回值。



相关代码如下:



/**

 * 使用callable 来实现线程类

 */

public class ThirdThread implements Callable<Integer>{



    private int ticket = 20;



    @Override

    public Integer call(){



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

            //获取当前的线程,只能用 Thread.currentThread() 获取当前的线程名

// Log.d(TAG,Thread.currentThread().getName()+" "+i);

            if(this.ticket>0){

                Log.e(TAG, Thread.currentThread().getName() + ", 卖票:ticket=" + ticket--);

            }

        }





        return ticket;

    }

}



private void starCallableThread(){

    ThirdThread thirdThread = new ThirdThread();

    FutureTask<Integer> task = new FutureTask<Integer>(thirdThread);



    new Thread(task,"有返回值的线程").start();



    try {

        Integer integer = task.get();

        Log.d(TAG,"starCallableThread, 子线程的返回值="+integer);



    } catch (InterruptedException e) {

        e.printStackTrace();

    } catch (ExecutionException e) {

        e.printStackTrace();

    }



}



运行结果:



![这里写图片描述](https://img-blog.csdn.net/20161221163503661?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5kcm9pZF9mcmVzaG1hbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)



> 注意:Callable的call() 方法允许声明抛出异常,并且允许带有返回值。  

> 程序最后调用FutureTask 对象的get()方法来返回Call()方法的返回值,导致主线程被阻塞,直到call()方法结束并返回为止。



* * *



#### **4.三种方式的对比**



采用继承Thread 类的方式创建多线程



劣势: 已经继承Thread类不能再继承其他父类。



优势: 编写简单



* * *



采用继承Runnable,Callable 接口的方式创建多线程



劣势: 编程稍微有点复杂,如果需要访问当前线程必须使用Thread.currentThread()



优势:  

(1)还可以继承其他类  

(2)多个线程可以共享一个target 对象,所以非常适合多个相同的线程来处理同一份资源的情况,从而将cpu,代码和数据分开,形成清晰的模型,较好的体现类面向对象的思想。



 



  



### 最后

> **面试题文档来啦,内容很多,485页!**
>
> **由于笔记的内容太多,没办法全部展示出来,下面只截取部分内容展示。**

# 1111道Java工程师必问面试题

![](https://img-blog.csdnimg.cn/img_convert/99f3e85402304dbce5508e8247bb720a.webp?x-oss-process=image/format,png)

**MyBatis 27题 + ZooKeeper 25题 + Dubbo 30题:**

![](https://img-blog.csdnimg.cn/img_convert/9c96d4c3aefb92c6fe4f086d9da6b1ad.webp?x-oss-process=image/format,png)

**Elasticsearch 24 题 +Memcached +** **Redis 40题:**

![](https://img-blog.csdnimg.cn/img_convert/97adcbe2d7c4b52574c1fe5046dbf0ef.webp?x-oss-process=image/format,png)

**Spring 26 题+ 微服务 27题+ Linux 45题:**

![](https://img-blog.csdnimg.cn/img_convert/b994c512bac9a3e372f2a56d864f42d2.webp?x-oss-process=image/format,png)

**Java面试题合集:**

![](https://img-blog.csdnimg.cn/img_convert/33abd79b2fa250a4ffd227445e433dfa.webp?x-oss-process=image/format,png)

mg-IuRj7UH7-1714317408142)]

**Elasticsearch 24 题 +Memcached +** **Redis 40题:**

[外链图片转存中...(img-ELhbAf19-1714317408143)]

**Spring 26 题+ 微服务 27题+ Linux 45题:**

[外链图片转存中...(img-akboQY7e-1714317408143)]

**Java面试题合集:**

[外链图片转存中...(img-c8OZWWpx-1714317408143)]

> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/topics/618154847)收录**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值