并发编程之多线程基础-Thread和Runnable的区别及联系(二)
上篇文章讲述了创建线程的常用方式
本篇主要分析一下Thread和Runnable两种方式创建线程的区别及联系
联系:
▶Thread类实现了Runable接口。
▶都需要重写里面Run方法。
区别:
▶Thread方式不支持多继承,Runnable方式支持多个实现
▶Runnable更容易实现资源共享,能多个线程同时处理一个资源。
疑惑分享:
本人在理解他们区别的时候
考虑到Thread类本身就是Runnable的实现类
所以产生了一个疑惑:-
为什么Runnable可以实现共享而Thread却不行呢
疑惑代码:
class Thread1 extends Thread {
int i = 100;
@Override
public void run() {
while (i > 0) {
try {
Thread.sleep(40L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (this) {
/*synchronized 不要直接放在run方法 应该放到循环里面 这样多个线程在循环的时候每次都能竞争锁 从而实现交替执行 否则一个线程执行完了另一个线程就没有执行的机会了*/
if (i > 0) {
/*
1.加判断是为了 如果当i=1的时候 此时两个线程都执行到了这里 一个线程得到锁进行减一操作那么i变为0 此时第二个线程再输出就会把0输出出来
2.第二个线程能够及时读取到i的值是由于synchronized既可以实现原子性又可以实现可见性*/
System.out.println(Thread.currentThread().getName() + "i:" + i);
i--;}}}
}}
public class TestThread {
public static void main(String[] args) {
Thread1 te1 = new Thread1();
Thread t1 = new Thread(te1, "window1");
Thread t2 = new Thread(te1, "window2");
t1.start();
t2.start();
}
}
下面我们就来聊一聊(有共同疑惑的朋友们可以参考一下):
首先我们要清楚Thread和Runnable两种方式的本质区别在哪里
我们知道无论使用哪种方式最终都会通过 Thread类对象调用start方法进行开启线程
本质的区别就在于:
Thread方式是调用无参构造方法
Runnable方式是调用带有Runnable参数的有参构造方法
我们说过Thread类实现了Runable接口
以上疑惑代码中就是向Thread构造方法中传递了一个Tel1参数
看似与Runnable没有关系
但实质上是属于常说的Runnable方式调用
对应源码:Thread(Runnable target, String name)
那么有参和无参有什么区别是什么呢,为什么runnable能实现资源共享:
参考源码:
this.target = paramRunnable;
public void run()
{
if (this.target != null)
this.target.run();
}
有参:
如果是参数中Runnable不为空
那么Thread run方法中最终执行的方法实际上是传进来Runnable中的run方法
所以使用Runnable方式 无论new出多少个Thread对象
最终执行的任务都是一样的
自然就实现了资源的共享
无参:
每次new出Thread对象
他们对应的成员变量是互不影响的
所以就不能达到资源共享的效果
涉及知识点:
JMM关于synchronized的两条规定:
1)线程解锁前,必须把共享变量的最新值刷新到主内存中
2)线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新获取最新的值
(注意:加锁与解锁需要是同一把锁)
通过以上两点,可以看到synchronized能够实现可见性。同时,由于synchronized具有同步锁,所以它也具有原子性
温馨提示:
▶在学习过程中理解一些概念或者结论不清晰的时候,一定要亲自动手结合着代码去分析,不要片面的理解一些知识点,一定要搞清实质。
▶本文内容如有不妥,恳请指正。
并发编程之多线程基础-Thread和Runnable的区别及联系(二)的更多相关文章
- C++11并发编程:多线程std::thread
一:概述 C++11引入了thread类,大大降低了多线程使用的复杂度,原先使用多线程只能用系统的API,无法解决跨平台问题,一套代码平台移植,对应多线程代码也必须要修改.现在在C++11中只需使用语 ...
- python并发编程之多线程基础知识点
1.线程理论知识 概念:指的是一条流水线的工作过程的总称,是一个抽象的概念,是CPU基本执行单位. 进程和线程之间的区别: 1. 进程仅仅是一个资源单位,其中包含程序运行所需的资源,而线程就相当于车间 ...
- java并发编程与多线程基础学习一
学习url:https://www.cnblogs.com/lixinjie/p/10817860.html https://www.cnblogs.com/JJJ1990/p/10496850.ht ...
- 并发编程之多线程基础-join方法及优先级(五)
join()方法作用 当在主线程当中执行到t1.join()方法时,就认为主线程应该把执行权让给t1 优先级 现代操作系统基本采用时分的形式调度运行的线程,线程分配得到的时间片的多少决定了线程使用处理 ...
- Java学习从菜鸟变大鸟之三 多线程中Thread 和Runnable的区别与运用
多线程机制是java中的一个特点,掌握它对后面的知识的理解至关重要,是java工程师的必备知识,多线程指在单个程序中可以运行多个不同的线程执行的不同的任务,线程是一个程序内部的顺序控制流.进程是静态的 ...
- Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁
Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...
- 三、多线程之Thread与Runnable的区别
Thread与Runnable的区别(用三个窗口同时出售10张车票为例子) 运行代码 运行结果 分析 System.out.println("开始测试多线程");class MyT ...
- Java 使用线程方式Thread和Runnable,以及Thread与Runnable的区别
一. java中实现线程的方式有Thread和Runnable Thread: public class Thread1 extends Thread{ @Override public void r ...
- Java并发编程笔记之基础总结(二)
一.线程中断 Java 中线程中断是一种线程间协作模式,通过设置线程的中断标志并不能直接终止该线程的执行,而是需要被中断的线程根据中断状态自行处理. 1.void interrupt() 方法:中断线 ...
随机推荐
- js跑步算法
<!DOCTYPE html> <html> <head> <title>JavaScript</title> <style> ...
- 不同线程不能获取其他线程设置的ThreadLocal里面的值
背景: 最近在项目用到了ThreadLocal,存放一些值.起线程异步获取ThreadLocal中的值,得到null.这是由于,ThreadLocal.get()会获取当前线程的一个map对象,以Th ...
- Java web service 异常
1.org/apache/commons/discovery/tools/DiscoverSingleton Exception in thread "main" java.lan ...
- Django组件——cookie与session
一.会话跟踪技术 1.什么是会话跟踪技术 可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应. 在JavaWeb中,客户向某一服务器发出第一个请求开始,会话就开始了,直 ...
- 【Linux】Linux远程登陆
登录任务 Windows主机--远程登录--Linux主机 一.登陆前提准备 1.1 确保网络通畅 确保从Windows 能够Ping通Linux 1.2 关闭Linux防火墙 //前提:以root管 ...
- struts1.3.10 和 hibernate 3.3.2 一起加载时 出现javax.servlet.ServletException: java.lang.NoSuchMethodError: antlr.collections.A 错误
struts1.3.10 需要导入一个 antlr-2.7.2.jar 的jar包: hibernate 3.3.2 需要导入一个 antlr-2.7.6.jar 的jar包,这两个包有冲突,所以需要 ...
- 解析angularjs中的绑定策略
一.首先回顾一下有哪些绑定策略? 看这个实在是有点抽象了,我们来看具体的实例分析吧! 二.简单的Demo实例 @绑定:传递一个字符串作为属性的值.比如 str : ‘@string’ 控制器中代码部分 ...
- adb工具包使用方法
ADB工具包总共有四个文件,两个exe后缀,两个dll后缀.里面还带有fastboot.exe下载后在PC上安装,如安装到D:\adb_tools-2.0目录,确认目录中带有fastboot.exe文 ...
- 在linux代码中打印函数调用的堆栈的方法
之前一直有这样的需求,当时问到,也没搜到方法,现在竟然既问到了,也搜到了,哎,世事真是不能强求啊! 在Linux内核调试中,经常用到的打印函数调用堆栈的方法非常简单,只需在需要查看堆栈的函数中加入: ...
- 第一次使用Git
这次的作业是关于GIT的,一开始我并不知道GIT是啥,百度了一下才知道Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理. Git 是 Linus Torvalds ...