java多线程学习-同步(synchronized)
(示例都是网上视频的)
假如两个线程同时调用一个方法输出字符串
public class SynchronizedTest extends Thread {
public static void main(String[] args) {
final SynchronizedTest st = new SynchronizedTest();
new Thread(new Runnable() {
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
st.outputStr("this is test");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
st.outputStr("okokokokokok");
}
}
}).start();
}
public void outputStr(String str){
for(int i=0;i<str.length();i++){
System.out.print(str.charAt(i));
}
System.out.println();
}
}
输出:
this is test
okokokokokok
this is test
okokokokokok
this is test
okokothis is test
kokokok
tokokokokokok
his is test
okokokokokok
this is test
okokthisokokokok
is test
okothkoiskokokok
is test
okokokothis is test
kokok
this iokokokokokok
s test
okokokothiskokok
is test
okokokokokokthis
is test
okthisok is tokokokoest
可以看出来,一开始输出还没问题,后来输出就乱了。
解决方法就是加上同步方法即在outputStr方法上加上同步关键字synchronized即可
public synchronized void outputStr(String str){
for(int i=0;i<str.length();i++){
System.out.print(str.charAt(i));
}
System.out.println();
}
synchronized :
当然synchronized不仅可以用在方法上,还可以用在对象上。
1.用在String上
public class SynchronizedTest2 {
public static void main(String[] args) {
final SynchronizedTest2 t2 = new SynchronizedTest2();
new Thread(new Runnable() {
public void run() {
while(true){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.outputStr("thread-1");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while(true){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.outputStr("thread-2");
}
}
}).start();
}
public void outputStr(String threadName){
String str = "123";
synchronized(str){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + " - "+System.currentTimeMillis()/1000);
}
}
}
输出:
thread-1 - 1475373023
thread-2 - 1475373024
thread-1 - 1475373025
thread-2 - 1475373026
thread-1 - 1475373027
可以看出,每一秒只有一个线程在运行,但是也不觉得是thread-1运行下,thread-2运行下,随机的。对字符串同步也可以,但是同步的必须是同一个对象才能互斥。
public void outputStr(String threadName){
String str = "123";
synchronized(threadName){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + " - "+System.currentTimeMillis()/1000);
}
}
这次synchronized里面同步的是threadName参数了
输出:
thread-1 - 1475373333
thread-2 - 1475373333
thread-1 - 1475373334
thread-2 - 1475373334
thread-1 - 1475373335
thread-2 - 1475373335
thread-1 - 1475373336
thread-2 - 1475373336
可以看出同一秒中两个线程都运行了,这里面两个线程就没有互斥。
public void outputStr(String threadName){
String str = "123";
synchronized(this){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + " - "+System.currentTimeMillis()/1000);
}
}
这时候调用同一SynchronizedTest2对象的线程在这个方法里都会互斥
但是如果把main方法改成这样
public class SynchronizedTest2 {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
SynchronizedTest2 t2 = new SynchronizedTest2();
while(true){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.outputStr("thread-1");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
SynchronizedTest2 t2 = new SynchronizedTest2();
while(true){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.outputStr("thread-2");
}
}
}).start();
}
public void outputStr(String threadName){
String str = "123";
synchronized(this){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + " - "+System.currentTimeMillis()/1000);
}
}
}
即每个线程都使用不同的SynchronizedTest2对象,这时输出:
thread-2 - 1475376542
thread-1 - 1475376542
thread-1 - 1475376543
thread-2 - 1475376543
thread-1 - 1475376544
thread-2 - 1475376544
thread-1 - 1475376545
thread-2 - 1475376545
可以看出此时两个线程并没有互斥。所以同步this只有使用同一个对象才会互斥。
3.用在类的字节码上
把outputStr方法改为
public void outputStr(String threadName){
String str = "123";
synchronized(SynchronizedTest2.class){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + " - "+System.currentTimeMillis()/1000);
}
}
这时不管main方法里面的两个线程使用是同一个SynchronizedTest2对象还是不同的对象,在调用这个方法的时候,都能互斥,不会同时运行。可能是因为字节码对象只有一个吧。
其实将synchronized放在方法上,好像和这样同步一样。
synchronized关键字暂时只想到这么多,写的有点乱。
java多线程学习-同步(synchronized)的更多相关文章
- Java多线程学习之synchronized总结
0.概述 synchronized是Java提供的内置的锁机制,来实现代对码块的同步访问,称为内置锁(Intrinsic Lock) .内置锁包括两部分:一个是作为锁的对象的引用,另一个是由这个锁保护 ...
- java多线程学习-同步之线程通信
这个示例是网上烂大街的,子线程循环100次,主线程循环50次,但是我试了很多次,而且从网上找了很多示例,其实多运行几次,看输出结果并不正确.不知道是我转牛角尖了,还是怎么了.也没有大神问,好痛苦.现在 ...
- Java 多线程(Thread) 同步(synchronized) 以及 wait, notify 相关 [实例介绍]
场景描述 有一家很大的商场,在某市有几个商品配送中心,并有几家分店,这家商场经营很多的商品,平时运营情况是这样的: 根据各分店的商品销售情况,给分店配送相应需求量的商品:并上架到分店指让的位置,供客户 ...
- Java多线程学习(二)synchronized关键字(2)
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79670775 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- Java多线程学习(二)synchronized关键字(1)
转载请备注地址: https://blog.csdn.net/qq_34337272/article/details/79655194 Java多线程学习(二)将分为两篇文章介绍synchronize ...
- Java多线程学习(转载)
Java多线程学习(转载) 时间:2015-03-14 13:53:14 阅读:137413 评论:4 收藏:3 [点我收藏+] 转载 :http://blog ...
- java多线程学习笔记——详细
一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...
- 【转】Java多线程学习
来源:http://www.cnblogs.com/samzeng/p/3546084.html Java多线程学习总结--线程概述及创建线程的方式(1) 在Java开发中,多线程是很常用的,用得好的 ...
- JAVA多线程学习笔记(1)
JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...
随机推荐
- ajax请求后弹开新页面被浏览器拦截
window.open()我想应该很多人都不陌生吧,它可以实现除用a标签以外来实现打开新窗口! 最近开发项目用到时,却遇到了麻烦,本来好好的弹出窗口,结果被浏览器无情的给拦截了! 代码如下: $.ge ...
- 【原创】Scrum模式也要根据自身特点微调,不能教条
手上的项目在用Scrum模式开发,运用的是禅道这个国产的平台,运作得还不错,具体如下: 1.整个开发团队有10个人,分为:新功能开发组和系统优化组,每组配备一个技术经理2.人员分在两个办公地点(同一城 ...
- U盘安装Win7操作系统
玩转Windows7系统镜像四部曲 Step 1: 下载Win7 ISO系统镜像 温馨提示:请您尽量选用Win7之家提供的官方原版镜像安装,因为正版比各种所谓的"精简版.纯净版" ...
- Apache Shiro 使用手册(一)Shiro架构介绍
一.什么是Shiro Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能: 认证 - 用户身份识别,常被称为用户"登录": 授权 - ...
- ASP.NET MVC利用ajax把action的JavaScript注册到页面并执行
相信大家在做Webform时经常会遇到在页面的后台CS文件中根据数据运行结果修改页面显示样式.显示(隐藏).或者弹出框,当时我们会用到ScriptManage或者Page来向页面注册一段js来实现页面 ...
- S7-1200 与 S7-200 的对比PPT
- Catalan数(数论)
Catalan数 [参考网址]http://www.cnblogs.com/gongxijun/p/3232682.html 记得当时我们队写过一个,差点超时,现在找到了公式,感觉还是挺简单的. 还要 ...
- iOS 手写输入法奔溃,替换隐藏键盘方法
{ UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:se ...
- ArcGIS Engine要素渲染和专题图制作(转)
摘要:Feature的常用的绘制方法包括:1.简单绘制:2.唯一值绘制/多字段唯一值绘制:3.点密度/多字段点密度绘制:4.数据分级绘制:5.质量图(饼图/直方图): 6.按比例尺渲染:7.比例符号渲 ...
- Android软件测试Monkey测试工具
前言: 最近开始研究Android自动化测试方法,对其中的一些工具.方法和框架做了一些简单的整理,其中包括android测试框架.CTS.Monkey.Monkeyrunner.benchmark.其 ...