Java多线程高并发学习笔记(一)——Thread&Runnable
进程与线程
首先来看百度百科关于进程的介绍:
进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。
直观一点:
windows的任务管理里面,我们看到的eclipse和360等等,都是进程。(想深入了解的可以看看计算机操作系统)
什么是线程?
线程是在一个进程独立运行的子任务。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。
打个比如说,我们都用的QQ软件,它是一个进程,我们可以和人一边聊天一边传输文件,这就是多线程。
为什么要使用多线程?
1.多线程可以充分的利用系统的cpu,达到更快的处理效果
2.提高系统的运行效率
想入更深入了解的可以重新学习计算机操作系统,这里就不多介绍了,接下来我们怎么用!(毕竟这才是关键)
Thread and Runnable
Java中实现线程有两个方式,一个是继承Thread,另一个是实现Runnable接口,首先来看继承Thread的第一个实例:
package com.chapter1; public class FirstThread { public static void main(String[] args) {
InnerThread thread = new InnerThread();
// 线程启动
thread.start();
} } class InnerThread extends Thread { // Override run方法,写入自己想要实现的业务
@Override
public void run() {
super.run();
System.out.println("Hello World!");
}
}
继承run方法的时候,我们通常会重写run方法,来实现自己的业务,接下来看,如何使用Runnable实现线程:
package com.chapter1; public class FirstRunnable { public static void main(String[] args) {
MyRunnable myRunnable;
myRunnable = new MyRunnable();
new Thread(myRunnable).start();
} } class MyRunnable implements Runnable { @Override
public void run() {
System.out.println("Hello World!");
}
}
Runnable是一个接口,接口意味着更加灵活一些,也是推荐使用实现Runable接口来写线程的。
现在我们看到的都是一个单线程的例子,接下来写一个多线程的:
package com.chapter1;
/**
* 多个线程实例
* @author tangj
*
*/
public class ManyThread { public static void main(String args[]) {
Runnable runnable = new MyRunnable2();
new Thread(runnable, "a").start();
new Thread(runnable, "b").start();
new Thread(runnable, "c").start();
new Thread(runnable, "d").start();
}
} class MyRunnable2 implements Runnable { int count = 0;
@Override
public void run() {
autoIncrement();
System.out.println(Thread.currentThread().getName()+"计算了"+"count:" + count);
}
// 执行自增操作
private void autoIncrement(){
count++;
}
}
我们来看下运行结果:
再运行一次
可以看到,多线程的执行是无序的,而且这个结果有点奇怪,难道不是从1增加到4吗,怎么会出现重复的?
在JVM中,执行自增操作的分为三个步骤:
1.取得现有值count
2.执行count+1操作
3.将count+1赋值给count.
所以就会遇到这样的情况,一个线程在取得count值的时候,count操作正处于第二个步骤,上一个线程执行的还未进行赋值操作,这就涉及到线程安全问题。
下面给出上一个例子的解决方案
package com.chapter1; /**
* 多个线程实例
*
* @author tangj
*
*/
public class ManyThread { public static void main(String args[]) {
Runnable runnable = new MyRunnable2();
new Thread(runnable, "a").start();
new Thread(runnable, "b").start();
new Thread(runnable, "c").start();
new Thread(runnable, "d").start();
}
} class MyRunnable2 implements Runnable { int count = 0; // 注意在这里增加了关键字 synchronized
@Override
synchronized public void run() {
autoIncrement();
System.out.println(Thread.currentThread().getName() + "计算了" + "count:" + count);
} // 执行自增操作
private void autoIncrement() {
count++;
}
}
来看输出结果(多执行几次):
我们可以看到:不管哪个线程先执行,最后的打印顺序肯定是递增的顺序。
接下来我们看另外一中实现方式:使用重入锁(ReentrantLock)
package com.chapter1; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class ManyThread2 { public static void main(String[] args) {
Runnable runnable = new MyRunnable3();
new Thread(runnable, "a").start();
new Thread(runnable, "b").start();
new Thread(runnable, "c").start();
new Thread(runnable, "d").start();
}
} class MyRunnable3 implements Runnable{ int count = 0;
// 使用重入锁ReentrantLock
Lock lock = new ReentrantLock(); @Override
public void run() {
// 锁住
lock.lock();
count++;
System.out.println(Thread.currentThread().getName() + "计算了" + "count:" + count);
// 解锁
lock.unlock();
} }
得到的结果也是整齐的递增顺序,说明它也是线程安全的。
总结
所以以后开发多线程的业务的时候,首先应该考虑的问题应该是这样的一个流程:
1.能否用单线程解决?(单线程本身就是线程安全的)
2.我开发的多线程业务是否线程安全?
线程安全是保证程序正常运行的关键,所以应该把线程安全作为开发多线程对于考虑的首要问题。
最后说两句:
本文所以代码都更新到我的github中,大家可以去clone或者Fork,我会持续更新的。
点击这里进入我的Github
喜欢的朋友可以点击下方的推荐,或者写个评论我们共同探讨Java高并发!!!
Java多线程高并发学习笔记(一)——Thread&Runnable的更多相关文章
- Java多线程高并发学习笔记——阻塞队列
在探讨可重入锁之后,接下来学习阻塞队列,这边篇文章也是断断续续的写了很久,因为最近开始学ssm框架,准备做一个自己的小网站,后续可能更新自己写网站的技术分享. 请尊重作者劳动成果,转载请标明原文链接: ...
- Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
锁的概念 从jdk发行1.5版本之后,在原来synchronize的基础上,增加了重入锁ReentrantLock. 本文就不介绍synchronize了,有兴趣的同学可以去了解一下,本文重点介绍Re ...
- JAVA多线程高并发学习笔记(三)——Callable、Future和FutureTask
为什么要是用Callable和Future Runnable的局限性 Executor采用Runnable作为基本的表达形式,虽然Runnable的run方法能够写入日志,写入文件,写入数据库等操作, ...
- Java多线程高并发学习笔记(三)——深入理解线程池
线程池最核心的一个类:ThreadPoolExecutor. 看一下该类的构造器: public ThreadPoolExecutor(int paramInt1, int paramInt2, lo ...
- Java 多线程高并发编程 笔记(一)
本篇文章主要是总结Java多线程/高并发编程的知识点,由浅入深,仅作自己的学习笔记,部分侵删. 一 . 基础知识点 1. 进程于线程的概念 2.线程创建的两种方式 注:public void run( ...
- JAVA 多线程和并发学习笔记(三)
Java并发编程中使用Executors类创建和管理线程的用法 1.类 Executors Executors类可以看做一个“工具类”.援引JDK1.6 API中的介绍: 此包中所定义的 Execut ...
- Java 多线程高并发编程 笔记(二)
1. 单例模式(在内存之中永远只有一个对象) 1.1 多线程安全单例模式——不使用同步锁 public class Singleton { private static Singleton sin=n ...
- JAVA 多线程和并发学习笔记(二)
一.Java中创建线程方法 1. 继承Thread类创建线程类 定义Thread类的子类,重写该类的run()方法.该方法为线程执行体. 创建Thread子类的实例.即线程对象. 调用线程对象的sta ...
- JAVA 多线程和并发学习笔记(四)
1. 多进程 实现并发最直接的方式是在操作系统级别使用进程,进程是运行在它自己的地址空间内的自包容的程序.多任务操作系统可以通过周期性地将CPU从一个进程切换到另一个进程,来实现同时运行多个进程. 尽 ...
随机推荐
- css3布局属性flex
html代码如下: <ul class="ul_box"> <li><a href="#">html</a>&l ...
- Angular中使用$watch监听
$watch简单使用 $watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你. $watch(watchExpression, listener, objectEqua ...
- 2017多校第9场 HDU 6170 Two strings DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6170 题意:给了2个字符串,其中第2个字符串包含.和*两种特别字符,问第二个字符串能否和第一个匹配. ...
- 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(五)用户接口层之提取媒体流数据
当RTSP客户端向RTSP服务端发送完PLAY命令后,RTSP服务端就会另外开启UDP端口(SDP协商定义的端口)发送RTP媒体流数据包.这些数据包之间会间隔一段时间(毫秒级)陆续被发送到RTSP客户 ...
- js中的分支与循环
一.js的分支结构 js的分支结构包括:if-else结构.多重if结构.嵌套if结构和switch-case结构 1.if-else结构 1.结构的写法: if(判断条件){ //条件为 ...
- 每次启动懂maven项目都必须关闭javaw.exe进程
最近几天一致在搞配置问题,今天总于解决了.下面说问题: 我发现我每次配置完maven build的goals运行,总是会出现TOMCAT绑定接口问题,我做的方法就是不断地关掉JAVAw.exe进程.但 ...
- [2017-08-07]ABP系列——QuickStartA:概述、思想、入门和HelloWorld
唔,说好的文章,欠了好久,先水一篇. 本系列目录:Abp介绍和经验分享-目录 概述 先表个态:对绝大多数人来说,ABP是成熟的,足以用到生产环境的. 最适合的:业务非常复杂且不追求极致性能的(这里并不 ...
- 深入浅出数据结构C语言版(15)——优先队列(堆)
在普通队列中,元素出队的顺序是由元素入队时间决定的,也就是谁先入队,谁先出队.但是有时候我们希望有这样的一个队列:谁先入队不重要,重要的是谁的"优先级高",优先级越高越先出队.这样 ...
- 哪有Python视频百度云链接?
说到Python视频哪个好,小编在这里不好下结论.毕竟孰好孰坏,只有合适的才是最好的.就像买鞋子,一双鞋子好不好,只有合脚才是真的好.不过,这里有些个人认为通俗易懂的Python视频可以分享给大家. ...
- 对 响应数据写在config文件的再次优化
之前写过 [基于moco的mock server 简单应用]这篇文章,然后自己这段时间也在做基金的接口测试,逛了一些论坛,然后对 响应数据写在config文件的再次优化,之前是把所有的响应数据都写到c ...