Java多线程的理解和实例
编写具有多线程程序经常会用到的方法:run(), start(), wait(), notify(), notifyAll(), sleep(), yield(), join()
还有一个关键字:synchronized
下面主要来讲讲:
线程的创建方式就不需要细说,就2种方式 Thread和Runnable
1.run()和start()
实例1:
public class ThreadTest extends Thread {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.print(" " + i);
}
}
public static void main(String[] args) {
new ThreadTest().start();
new ThreadTest().start();
}
}
这是一个简单的多线程例子
实例2:
public class ThreadTest implements Runnable {
public synchronized void run() {
for (int i = 0; i < 10; i++) {
System.out.print(" " + i);
}
}
public static void main(String[] args) {
Runnable r1 = new ThreadTest();
Runnable r2 = new ThreadTest();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
在这个例子中,run被加上了synchronized,这个程序输出的结果是什么呢?t1和t2是2个对象的线程,不同对象的线程是不同的,所以在这个程序中synchronized 并没有起到作用,对于synchronized的定义来说,是针对同一对象的多个线程来说的,在某一时刻只有一个线程能访问此对象的数据
实例3:
public class ThreadTest implements Runnable {
public synchronized void run() {
for (int i = 0; i < 10; i++) {
System.out.print(" " + i);
}
}
public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}
实例4:
public class ThreadTest implements Runnable {
public void run() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.print(" " + i);
}
}
}
public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}
实例3和4中,synchronized控制了线程对象的数据共享,输出的结果只能是0123456789,3和4其实区别就是synchronized作用范围
实例5:
public class ThreadTest implements Runnable {
public void run() {
for (int k = 0; k < 5; k++) {
System.out.println(Thread.currentThread().getName()
+ " : for loop : " + k);
}
synchronized (this) {
for (int k = 0; k < 5; k++) {
System.out.println(Thread.currentThread().getName()
+ " : synchronized for loop : " + k);
}
}
}
public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r, "t1_name");
Thread t2 = new Thread(r, "t2_name");
t1.start();
t2.start();
}
}
输出结果是:
t1_name : for loop : 0
t1_name : for loop : 1
t1_name : for loop : 2
t2_name : for loop : 0
t1_name : for loop : 3
t2_name : for loop : 1
t1_name : for loop : 4
t2_name : for loop : 2
t1_name : synchronized for loop : 0
t2_name : for loop : 3
t1_name : synchronized for loop : 1
t2_name : for loop : 4
t1_name : synchronized for loop : 2
t1_name : synchronized for loop : 3
t1_name : synchronized for loop : 4
t2_name : synchronized for loop : 0
t2_name : synchronized for loop : 1
t2_name : synchronized for loop : 2
t2_name : synchronized for loop : 3
t2_name : synchronized for loop : 4
第一个for循环没有收synchronized保护,所以t1,t2的执行方式是交错的,第二个循环受synchronized保护,所以结果是有规律的
2.sleep()方法:
实例6:
public class ThreadTest implements Runnable {
public void run() {
for (int k = 0; k < 5; k++) {
if (k == 2) {
try {
Thread.currentThread().sleep(5000);
}
catch (Exception e) {}
}
System.out.println(Thread.currentThread().getName()+ " : " + k);
}
}
public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r, "t1_name");
Thread t2 = new Thread(r, "t2_name");
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
}
}
输出结果:
t1_name : 0
t1_name : 1
t2_name : 0
t2_name : 1
t1_name : 2
t1_name : 3
t1_name : 4
t2_name : 2
t2_name : 3
t2_name : 4
t1被设置了最高的优先级,t2被设置了最低的优先级,t1不执行完,t2就没有机会执行。但由于t1在执行的中途休息了5秒中,这使得t2就有机会执行了。
3.join()方法:主要是让调用改方法的thread完成run方法里面的东西后, 在执行join()方法后面的代码
实例7:
public class ThreadTest implements Runnable {
public static int a = 0;
public void run() {
for (int k = 0; k < 5; k++) {
a = a + 1;
}
}
public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t = new Thread(r);
t.start();
System.out.println(a);
}
}
实例8:
public class ThreadTest implements Runnable {
public static int a = 0;
public void run() {
for (int k = 0; k < 5; k++) {
a = a + 1;
}
public static void main(String[] args) throws Exception {
Runnable r = new ThreadTest();
Thread t = new Thread(r);
t.start();
t.join();
System.out.println(a);
}
}
实例7和8区别就在于加了个join方法,join能保证调用此方法的线程对象完成对应run方法中的内容,所以实例7来说,不确定输出的是什么,而实例8肯定输出的是5
4.yield()方法:
yield() 方法与sleep() 方法相似,只是它不能由用户指定线程暂停多长时间。按照SUN的说法:sleep方法可以使低优先级的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会。而yield()方法只能使同优先级的线程有执行的机会。
实例9:
public class ThreadTest implements Runnable {
public void run() {
8
for (int k = 0; k < 5; k++) {
if (k == 5 && Thread.currentThread().getName().equals("t1")) {
Thread.yield();
}
System.out.println(Thread.currentThread().getName()
+ " : " + k);
}
}
public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r, "t1");
Thread t2 = new Thread(r, "t2");
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
}
}
输出结果:
t1 : 0
t1 : 1
t1 : 2
t1 : 3
t1 : 4
t2 : 0
t2 : 1
t2 : 2
t2 : 3
t2 : 4
从输出结果上看,yield() 方法不会使不同优先级的线程有执行的机会。本例中t1和t2不同的优先级,在t1被yield的时候,t2也是一点机会也没有,只有等到高优先级t1执行完成之后才有执行的机会,而sleep并不是,可以看看实例6
5.wait(),notify(),notifyAll()
首先说明:wait(), notify(),notifyAll()
这些方法由java.lang.Object类提供,而上面讲到的方法都是由java.lang.Thread类提供(Thread类实现了Runnable接口)。
这三个方法用于协调多个线程对共享数据的存取,所以这三个方法只能在synchronized中使用
实例10:
public class ThreadTest implements Runnable {
public static int shareVar = 0;
public synchronized void run() {
if (shareVar == 0) {
for (int i = 0; i < 10; i++) {
shareVar++;
if (shareVar == 5) {
try {
this.wait();
}
catch (Exception e) {}
}
}
}
if (shareVar != 0) {
System.out.print(Thread.currentThread().getName());
System.out.println(" shareVar = " + shareVar);
this.notify();
}
}
public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r, "t1");
Thread t2 = new Thread(r, "t2");
t1.start();
t2.start();
}
}
输出结果:
t2 shareVar = 5
t1 shareVar = 10
过程:t1线程最先执行。由于初始状态下shareVar为0,t1将使shareVar连续加1,当shareVar的值为5时,t1调用wait() 方法,
t1将处于休息状态,同时释放锁标志。这时t2得到了锁标志开始执行,shareVar的值已经变为5,所以t2直接输出shareVar的值,
然后再调用notify()
方法唤醒t1。t1接着上次休息前的进度继续执行,把shareVar的值一直加到10,由于此刻shareVar的值不为0,
所以t1将输出此刻shareVar的值,然后再调用notify()
方法,由于此刻已经没有等待锁标志的线程,所以此调用语句不起任何作用。
Java多线程的理解和实例的更多相关文章
- java多线程的理解
java多线程的理解 线程的5种状态:新建,就绪,运行,阻塞,死亡. Thread.sleep:线程 运行状态 转为 阻塞状态,(其它线程启动运行) Thread.yield: 线程 运行 ...
- (转载)Java多线程入门理解
转载出处http://blog.csdn.net/evankaka 写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更 ...
- synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解
本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁 ...
- 温故知新-java多线程&深入理解线程池
文章目录 摘要 java中的线程 java中的线程池 线程池技术 线程池的实现原理 简述 ThreadPoolExecutor是如何运行的? 线程池运行的状态和线程数量 任务执行机制 队列缓存 Wor ...
- 谈谈你对Java多线程的理解以及多线程的实现方式
说线程之前先说进程,何为进程?进程就是正在进行中的程序.比如电脑同时在运行QQ进程.cmd进程.wps进程.飞秋进程等.在某一时刻,CPU只能执行一个程序,只是在做快速切换,我们肉眼看不出来. 比如: ...
- Java多线程深入理解
在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口. 对于直接继承Thread的类来说,代码大致框架是: ? 1 2 3 4 5 6 7 8 9 10 ...
- Java多线程死锁的产生实例
死锁产生的四个必要条件: (1) 互斥条件:一个资源每次只能被一个进程使用.(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放.(3) 不剥夺条件:进程已获得的资源,在末使用完 ...
- Java多线程 -- 深入理解JMM(Java内存模型) --(五)锁
锁的释放-获取建立的happens before 关系 锁是Java并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息. 下面是锁释放-获取的示例代 ...
- Java 多线程并发 Future+callable 实例
需求:一个业务实现 查询, 因为 要查询十几次, 所以每个平均0.6秒, 之前只有主线程一步步查 ,结果用了10秒,效率十分低下 , 于是改用线程池并发: 以下是代码设计: 1.线程池工具类: pac ...
随机推荐
- 数学相关【真·NOIP】
数论相关 上来就不会的gcd相关.见SCB他威胁我去掉了一个后缀的blog好了:https://blog.csdn.net/suncongbo/article/details/82935140(已经过 ...
- spring boot 热部署devtools实现(成功,主要是添加依赖后配置setting)
1.devtools spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署,提高开发者的开发效率,无需手动重启Spring Boot ...
- poj 3468: A Simple Problem with Integers (树状数组区间更新)
题目链接: http://poj.org/problem?id=3468 题目是对一个数组,支持两种操作 操作C:对下标从a到b的每个元素,值增加c: 操作Q:对求下标从a到b的元素值之和. 这道题也 ...
- mybatis源码分析之04Mapper接口的动态代理
在工作中,使用mybatis操作数据库,只需要提供一个接口类,定义一些方法,然后调用接口里面的方法就可以CRUD,感觉是牛了一逼! 该篇就是记录一下,mybatis是如何完成这波骚操作的,即分析我们测 ...
- 基于oracle 的PL/SQL编程 - 存储过程
接上篇,游标使用的语句,相当于一段匿名的函数,窗口关闭了就不存在了.如果想要窗口关闭了,还能继续执行那段代码,就需要存储过程了: PLSQL是指一个个PLSQL的业务处理过程存储起来进行复用,这些被存 ...
- SpringMvc处理模型数据(也就是从数据库中查询出来的数据放到请求域中)
这讲的是从数据库中查询到的数据,存放到请求域中.然后页面上直接可以从请求域中获取值. 有4种方式: 1):ModelAndView 是作为一个对象. /** * 目标方法的返回值可以是 Model ...
- PHP curl_getinfo函数
curl_getinfo — 获取一个cURL连接资源句柄的信息 说明 mixed curl_getinfo ( resource $ch [, int $opt = 0 ] ) 获取最后一次传输的相 ...
- LDD3 第7章 Time,Delays and Deferred Work
处理时间委托包括如下任务,按复杂度依次上升: 测量时间流失和比较时间 知道当前时间 指定时间量的延时操作 调度异步函数在之后的时间发生 一.测量时间流失 系统定时硬件规律的产生定时器中断,在内核启动阶 ...
- flask-路转换器
from flask import Flask, render_template from werkzeug.routing import BaseConverter # 配置regex路由转换器 # ...
- PHP抓取远程图片到本地保存(如何把错误信息用text文件写入)
最近在工作中需要开发了一个用户素材功能,里面需要将网上的各种图片素材进行本地化存储.于是在网上找了一些相关资料,并根据自身开发需要,整理了一下主要的逻辑代码. /** * PHP将网页上的图片攫取到本 ...