代码如下:
package com.bohai.thread;
public class ThreadNoSynchronized {
public static void main(String[] args) {
ShareData oShare = new ShareData(); // 创建,初始化ShareData对象oShare
ThreadDemo th1 = new ThreadDemo("Thread1", oShare); // 创建线程th1
ThreadDemo th2 = new ThreadDemo("Thread2", oShare); // 创建线程th2
th1.start(); // 启动线程th1
th2.start(); // 启动线程th2
}
}
class ShareData {
public static String szData = ""; // 声明,并初始化字符串数据域,作为共享数据
}
class ThreadDemo extends Thread {
private ShareData oShare; // 声明,并初始化ShareData 数据域
ThreadDemo() {
} // 声明,并实现ThreadDemo 构造方法
// 声明,并实现ThreadDemo 带参数的构造方法
ThreadDemo(String szName, ShareData oShare) {
super(szName); // 调用父类的构造方法
this.oShare = oShare; // 初始化oShare域
}
public void run() {
for (int i = 0; i < 10; i++) {
if (this.getName().equals("Thread1")) {
oShare.szData = "这是第 1 个线程";
// 为了演示产生的问题,这里设置一次睡眠
try {
Thread.sleep((int) Math.random() * 100); // 休眠
} catch (InterruptedException e) { // 捕获异常
}
System.out.println(this.getName() + ":" + oShare.szData); // 输出字符串信息
} else if (this.getName().equals("Thread2")) {
oShare.szData = "这是第 2 个线程";
// 为了演示产生的问题,这里设置一次睡眠
try {
Thread.sleep((int) Math.random() * 100); // 线程休眠
} catch (InterruptedException e) // 捕获异常
{
}
System.out.println(this.getName() + ":" + oShare.szData); // 输出字符串信息
}
}
}
}
执行结果如下:
Thread1:这是第 2 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
从结果可以看出,这不是我们期望的结果:优化后代码如下:
package com.bohai.thread;
public class ThreadNoSynchronized {
public static void main(String[] args) {
ShareData oShare = new ShareData(); // 创建,初始化ShareData对象oShare
ThreadDemo th1 = new ThreadDemo("Thread1", oShare); // 创建线程th1
ThreadDemo th2 = new ThreadDemo("Thread2", oShare); // 创建线程th2
th1.start(); // 启动线程th1
th2.start(); // 启动线程th2
}
}
class ShareData {
public static String szData = ""; // 声明,并初始化字符串数据域,作为共享数据
}
class ThreadDemo extends Thread {
private ShareData oShare; // 声明,并初始化ShareData 数据域
ThreadDemo() {
} // 声明,并实现ThreadDemo 构造方法
// 声明,并实现ThreadDemo 带参数的构造方法
ThreadDemo(String szName, ShareData oShare) {
super(szName); // 调用父类的构造方法
this.oShare = oShare; // 初始化oShare域
}
public void run() {
for (int i = 0; i < 10; i++) {
if (this.getName().equals("Thread1")) {
synchronized (oShare) {
oShare.szData = "这是第 1 个线程";
}
// 为了演示产生的问题,这里设置一次睡眠
try {
Thread.sleep((int) Math.random() * 100); // 休眠
} catch (InterruptedException e) { // 捕获异常
}
System.out.println(this.getName() + ":" + oShare.szData); // 输出字符串信息
} else if (this.getName().equals("Thread2")) {
synchronized (oShare) {
oShare.szData = "这是第 2 个线程";
}
// 为了演示产生的问题,这里设置一次睡眠
try {
Thread.sleep((int) Math.random() * 100); // 线程休眠
} catch (InterruptedException e) // 捕获异常
{
}
System.out.println(this.getName() + ":" + oShare.szData); // 输出字符串信息
}
}
}
}
对共享变量需要进行同步。不要在方法上使用 synchronized。