java中线程的几种实现方式
1. 继承Thread类来实现
class MyThread extends Thread{
@Override
public void run() {
System.out.println("myThread is running");
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
由于在java中采用单继承的模式,因此继承Thread类有一个明显的缺点就是占用了唯一的extends,是的我们无法在继承其它的类,因此一般不会采用这种方式。
2. 实现Runnable接口
class MyRun implements Runnable{
@Override
public void run() {
System.out.println("myThread is running");
}
}
public static void main(String[] args) {
// MyThread thread = new MyThread();
// thread.start();
Thread thread1 = new Thread(new MyRun());
thread1.start();
}
我们通过Runnable接口来实现线程实际上是策略模式的实现(策略模式可以参考我之前写的博客)。我们通过实现 run()来实现自己要完成的事情。
3. 通过Callable来实现可返回值的线程
class MyCallable implements Callable{ //实现接口Callable
@Override
public Object call() throws Exception {
return "my callable is running";
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
// MyThread thread = new MyThread();
// thread.start();
// Thread thread1 = new Thread(new MyRun());
// thread1.start();
FutureTask task = new FutureTask(new MyCallable()); //构造一个FutureTask,FutureTask间接继承了Runnable接口
Thread thread = new Thread(task);
thread.start();
System.out.println(task.get());
}
使用Callable接口相当于在run()方法的基础上再次使用了策略模式,将call()方法留了出来,用以实现并保存方法执行的结果。我们可以看一下源码。
public class FutureTask<V> implements RunnableFuture<V> { //这是FutureTask类,本身间接实现了Runnable接口
这是FutureTask中的run()方法
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call(); //可以发现在FutureTask中的run方法中调用了call()方法,而这个call()方法通过构造器传入,我们可以自由实现。相当于也是策略模式的实现。
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result); //在这里将线程运行的结果进行了保存
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
protected void set(V v) { //这是set()函数
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v; //在这里将返回值赋给了outcome
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
4. 总结
(1)继承Thread类后,我们需要重写run()方法来实现自己的线程。
(2)对于实现Runnable接口,该接口相当于是策略接口。
(3)对于实现Callable接口,在FutureTask中给出了run()方法的具体实现(FutureTask间接实现了Runnable接口),并且流出了另外的Callable策略接口来让我们实现可返回值的线程实现。
java中线程的几种实现方式的更多相关文章
- java中线程的三种实现方式
一下记录下线程的3中实现方式:Thread,Runnable,Callable 不需要返回值时,建议使用Runnable:有返回值时建议使用Callable 代码如下所示: package com.f ...
- java中线程分两种,守护线程和用户线程。
java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性 ...
- JAVA中单例模式的几种实现方式
1 线程不安全的实现方法 首先介绍java中最基本的单例模式实现方式,我们可以在一些初级的java书中看到.这种实现方法不是线程安全的,所以在项目实践中如果涉及到线程安全就不会使用这种方式.但是如果不 ...
- 【转载】JAVA中线程的两种实现方法-实现Runnable接口和继承Thread类
转自: http://blog.csdn.net/sunguangran/article/details/6069317 非常感谢原作者,整理的这么详细. 在java中可有两种方式实现多线程,一种是继 ...
- Java中String对象两种赋值方式的区别
本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...
- Java创建线程的三种主要方式
Java创建线程的主要方式 一.继承Thread类创建 通过继承Thread并且重写其run(),run方法中即线程执行任务.创建后的子类通过调用 start() 方法即可执行线程方法. 通过继承Th ...
- java中线程的几种状态和停止线程的方法
1.线程的状态图 需要注意的是:线程调用start方法是使得线程到达就绪状态而不是运行状态 2.停止线程的两种方法 1)自然停止:线程体自然执行完毕 2)外部干涉:通过线程体标识 1.线程类中定义线程 ...
- 细说java中Map的两种迭代方式
曾经对java中迭代方式总是迷迷糊糊的,今天总算弄懂了.特意的总结了一下.基本是算是理解透彻了. 1.再说Map之前先说下Iterator: Iterator主要用于遍历(即迭代訪问)Collecti ...
- Java中Map的4种遍历方式
第一种方式:这是平常用的最多也最可取的一种遍历方式. for (Map.Entry<String, Object> entry : map.entrySet()) { System.out ...
随机推荐
- 【java】使用java.util的【Collections】简化List创建
我们在创建一个List并往其中加入一个元素的时候一般会这么做: public List<User> getCurrentUser() { List<User> users = ...
- http://t.cn/xxxxx的短链接如何生成?
var convertStr = encodeURIComponent(urlStr); //转换的原链接可能存在"&"这样的特殊符号,导致原链接的某些字段会被当做ajax ...
- ASCII, Unicode, UTF-8
(本文参考:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html) 1. ASCII码 我们知道,在计算机内部,所有的 ...
- 【并发编程】ThreadLocal的兄弟InheritableThreadLocal
本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 引子 public class InheritableT ...
- 华为ARM64服务器上手体验--不吹不黑,用实际应用来看看TaiShan鲲鹏的表现
背景 中美贸易冲突以来,相信最大的感受,并不是我对你加多少关税,而是我有,可我不卖给你."禁售"成了市场经济中最大的竞争力. 相信也是因为这个原因,华为"备胎转正&quo ...
- 论文阅读 | Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks
简述 在文本语义相似度等句子对的回归任务上,BERT , RoBERTa 拿到sota. 但是,它要求两个句子都被输入到网络中,从而导致巨大开销:从10000个句子集合中找到最相似的sentence- ...
- KVM http网络加载镜像报错(mount: wrong fs type, bad option, bad superblock on /dev/loop0)
curl: (23) Failed writing body (7818 != 16384)loop: module loadeddracut-initqueue[579]: mount: wrong ...
- 编码规范(c#)
万丈高楼平地起,好的编码风格能让别人撸起来更带劲,反之则想吐槽这是哪个傻X写的,这都是些什么乱七八糟的玩意? 然后看后面的注释发现是自己以前写的,那场面一度很尴尬.... 规约不是规则,不是一定要这样 ...
- mybatis注解
@select查詢 @insert添加 @delete刪除 @update修改 @Results自关联 @Results映射 @One UserByRole表: RoleByUser表: @Many ...
- 第一节知识点:.net与c#的概念
1.什么是.net .net一般指的是.NET Framework框架,一种平台,一种技术:.NET 是微软的新一代技术平台,以构建互联互通的应用系统.这些应用程序的开发和运行必须有 ...