SyncDemo1.java
package day09_2;
/**
* 多线程并发安全问题
* 当多个线程并发访问同一个资源时,由于线程切换时机不确定
* 导致执行代码顺序的混乱,从而出现执行未按设计顺序
* 运行导致出现各种错误,严重时可能导致系统瘫痪。
* @author soft01
*
*/
public class am01_SyncDemo1 {
public static void main(String[] args) {
Table table = new Table();
Thread t1 = new Thread() {
public void run(){
while(true) {
int bean = table.getBean();
Thread.yield();
System.out.println(getName()+":"+bean);
}
}
};
Thread t2 = new Thread() {
public void run() {
while(true) {
int bean = table.getBean();
Thread.yield();
System.out.println(getName()+":"+bean);
}
}
};
t1.start();
t2.start();
}
}
class Table{
private int beans = 20;
/*
* 当一个方法是用synchronized修饰后,该方法
* 成为同步方法,即:多个线程不能同一时间在该方
* 法内执行。只能一个线程一个线程的执行该方法。
*
* 在一个方法上使用synchronized,那么同步监视器
* 对象是该方法所属对象,即:方法中的“this”.
*/
public synchronized int getBean() {
if(beans==0) {
throw new RuntimeException("没有豆子了");
}
Thread.yield();
return beans--;
}
}
SyncDemo2.java
package day09_2;
/**
* 有效缩小同步范围可以在保证并发安全的前提下提高
* 并发执行效率.
*
* 同步块,同步块可以更精确的控制需要同步的代码片段。
* @author soft01
*
*/
public class am02_SyncDemo2 {
public static void main(String[] args) {
Shop shop = new Shop();
Thread t1 = new Thread() {
public void run() {
shop.buy();
}
};
Thread t2 = new Thread() {
public void run() {
shop.buy();
}
};
t1.start();
t2.start();
}
}
class Shop{
// public synchronized void buy() {
public void buy() {
try {
Thread t = Thread.currentThread();
System.out.println(t.getName()+":正在选衣服");
Thread.sleep(5000);
/*
* 同步块:
* synchronized(同步监视器对象){
* 需要同步执行的代码片段
* }
* 同步监视器对象可以是java中任何类的实例,
* 只要保证多个线程看到的是“同一个”对象,
* 那么这些线程在执行同步块中的代码是就是
* 同步执行的。
*/
synchronized(new Object()) {
System.out.println(t.getName()+":正在试衣服");
Thread.sleep(5000);
}
System.out.println(t.getName()+":结帐走人");
}catch (Exception e){
}
}
}
SysncDemo3.java
package day09_2;
/**
* 静态方法使用synchronized修饰后,该方法一定具有
* 同步效果
* @author soft01
*
*/
public class am03_SyncDemo3 {
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
Foo.dosome();
}
};
Thread t2 = new Thread() {
public void run() {
Foo.dosome();
}
};
t1.start();
t2.start();
}
}
class Foo{
public synchronized static void dosome() {
Thread t = Thread.currentThread();
System.out.println(t.getName()+":正在运行dosome方法");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t.getName()+":运行doSome完毕");
}
}
SyncDemo4.java
package day09_2;
/**
* synchronized的互斥性
*
* synchronized修饰多段代码,但是这些同步块的同步
* 监视器对象是同一个时,那么这些代码间就是互斥的.
* 多个线程不能同时在这些代码中运行.
*
* @author soft01
*
*/
public class pm01_SysncDemo4 {
public static void main(String[] args) {
Coo coo =new Coo();
Thread t1 = new Thread() {
public void run() {
coo.methodA();
}
};
Thread t2 = new Thread() {
public void run() {
coo.methodB();
}
};
t1.start();
t2.start();
}
}
class Coo{
public synchronized void methodA() {
try {
Thread t = Thread.currentThread();
System.out.println(t.getName()+":正在执行A方法...");
Thread.sleep(5000);
System.out.println(t.getName()+":执行A方法完毕!");
}catch(Exception e) {
e.printStackTrace();
}
}
public synchronized void methodB() {
try {
Thread t = Thread.currentThread();
System.out.println(t.getName()+":正在执行B方法...");
Thread.sleep(5000);
System.out.println(t.getName()+":执行B方法完毕!");
}catch(Exception e) {
e.printStackTrace();
}
}
}
SyncAPIDemo.java
/**
* StringBuilder不是线程安全的,当多个线程操作
* 同一个字符串时应当使用StringBuffer
*
* 对于集合而言,常用的实现类:ArrayList,LinkedList
* HashSet它们都不是线程安全的.
* Collections可以将现有的集合转换为线程安全的
* @author soft01
*
*/
public class pm02_SyncAPIDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
System.out.println(list);
/*
* 将给定List集合转换为线程安全的List
*/
list = Collections.synchronizedList(list);
System.out.println(list);
Set<String> set = new HashSet<String>(list);
System.out.println(set);
/*
* 将给定的Set集合转换为线程安全的
*/
set = Collections.synchronizedSet(set);
System.out.println(set);
/*
* 线程安全的集合也不与迭代器遍历集合元素的操作
* 互斥,需要注意。
*/
}
}