1、在Java多线程中,没用使用synchronized关键字:
// 业务类
class Example {
// threadName 线程名称
public void executeOne(String threadName) {
for (int i = 0; i < 10; ++i) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + ": " + i);
}
}
}
// 控制类
class ThreadOne extends Thread {
private Example example;
private String threadName; // 线程名称。在多线程时以示区别
public ThreadOne(Example example, String threadName) {
this.example = example;
this.threadName = threadName;
}
public void run() {
this.example.executeOne(this.threadName);
}
}
// 测试类
public class ThradTest {
public static void main(String[] args) {
Example one = new Example();
Thread t1 = new ThreadOne(one,"One");
Thread t2 = new ThreadOne(one,"Two");
t1.start();
t2.start();
}
}
在多线程中没有使用synchronized关键字时,两个线程同时执行executeOne,执行结果是没有先后顺序,也无法预知结果。某一次执行结果为:
Two: 0
One: 0
One: 1
Two: 1
One: 2
Two: 2
One: 3
Two: 3
Two: 4
One: 4
One: 5
Two: 5
One: 6
Two: 6
Two: 7
One: 7
One: 8
Two: 8
One: 9
Two: 9
2、在Java多线程中,使用synchronized关键字,且多线程操作同一对象:
只对业务类进行修改,也就是在executeOne方法名前添加关键字synchronized。修改结果如下:
// 业务类
class Example {
// threadName 线程名称
public synchronized void executeOne(String threadName) {
for (int i = 0; i < 10; ++i) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + ": " + i);
}
}
}
在多线程中使用synchronized关键字,两个线程按先后顺序执行
executeOne方法,结果有先后顺序,是可预知的结果。运行结果如下:
One: 0
One: 1
One: 2
One: 3
One: 4
One: 5
One: 6
One: 7
One: 8
One: 9
Two: 0
Two: 1
Two: 2
Two: 3
Two: 4
Two: 5
Two: 6
Two: 7
Two: 8
Two: 9
执行结果为什么有先后顺序呢?是因为使用synchronized关键字修饰executeOne方法。在第一个线程t1执行时,给业务类对象one加上了锁。第二个线程t2在t1线程未执行完成时,处于等待状态,也就不能执行one对象中的executeOne方法。待t1线程执行完毕,并释放了锁,t2线程就可以执行one对象中的executeOne方法。
3、第1、2点中,多线程都是处理同一个one对象,接下来使用多线程处理不同对象。在第2点java代码的基础上修改测试类代码。修改结果如下:
// 测试类
public class ThradTest {
public static void main(String[] args) {
Example one = new Example();
Example two = new Example();
Thread t1 = new ThreadOne(one,"One");
Thread t2 = new ThreadOne(two,"Two");
t1.start();
t2.start();
}
}
运行结果如下:
One: 0
Two: 0
One: 1
Two: 1
Two: 2
One: 2
Two: 3
One: 3
Two: 4
One: 4
One: 5
Two: 5
One: 6
Two: 6
Two: 7
One: 7
One: 8
Two: 8
Two: 9
One: 9
执行结果与第1点相似,也是没有顺序。原因:t1线程在执行操作时,给one对象加上锁,而t2线程执行时,是对two对象执行操作,不是对one对象操作。也就是两个线程处理不同的对象,执行结果各不受影响。
4、在第3点的基础上,我们给业务类Example类中executeOne方法前添加static关键字,执行结果又有什么不同之处
// 业务类
class Example {
// threadName 线程名称
public synchronized static void executeOne(String threadName) {
for (int i = 0; i < 10; ++i) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + ": " + i);
}
}
}
执行结果如下:
One: 05、多个线程(ThreadOne、ThreadTwo)执行同一业务类(Example)不同方法(该方法用synchronized修饰),且多线程处理的是同一对象
// 业务类
class Example {
// threadName 线程名称
public synchronized void executeOne(String threadName) {
for (int i = 0; i < 10; ++i) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + ": " + i);
}
}
public synchronized void executeTwo(String threadName) {
for (int i = 0; i < 10; ++i) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + ": " + i);
}
}
}
// 控制类
class ThreadOne extends Thread {
private Example example;
private String threadName; // 线程名称。在多线程时以示区别
public ThreadOne(Example example, String threadName) {
this.example = example;
this.threadName = threadName;
}
public void run() {
this.example.executeOne(this.threadName);
}
}
class ThreadTwo extends Thread {
private Example example;
private String threadName; // 线程名称。在多线程时以示区别
public ThreadTwo(Example example, String threadName) {
this.example = example;
this.threadName = threadName;
}
public void run() {
this.example.executeTwo(this.threadName);
}
}
// 测试类
public class ThradTest {
public static void main(String[] args) {
Example one = new Example();
Thread t1 = new ThreadOne(one,"One");
Thread t2 = new ThreadTwo(one,"Two");
t1.start();
t2.start();
}
}
执行结果与第2点相同。原因:多线程执行操作的是同一个对象。t1线程执行操作时,会给one对象加锁,t2线程就不能操作one对象,t2线程也就处于等待状态,等待t1线程释放锁。
6、多个线程(ThreadOne、ThreadTwo)执行同一业务类(Example)不同方法(该方法用synchronized修饰),且多线程处理的是不同对象
修改第5点中的测试类即可,修改结果为:
// 测试类
public class ThradTest {
public static void main(String[] args) {
Example one = new Example();
Example two = new Example();
Thread t1 = new ThreadOne(one,"One");
Thread t2 = new ThreadTwo(two,"Two");
t1.start();
t2.start();
}
}
执行结果与第3点类似。原因:t1线程执行操作对象与t2线程操作对象不同。t1线程操作时,给one对象加锁,并非给two加锁。t2对象操作的是two对象
7、synchronized代码块
1)代码块在非静态方法中
// 业务类
class Example {
// threadName 线程名称
public void executeOne(String threadName) {
synchronized (this) {
for (int i = 0; i < 10; ++i) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + ": " + i);
}
}
}
}
// 控制类
class ThreadOne extends Thread {
private Example example;
private String threadName; // 线程名称。在多线程时以示区别
public ThreadOne(Example example, String threadName) {
this.example = example;
this.threadName = threadName;
}
public void run() {
this.example.executeOne(this.threadName);
}
}
// 测试类
public class ThradTest {
public static void main(String[] args) {
Example one = new Example();
Thread t1 = new ThreadOne(one,"One");
Thread t2 = new ThreadOne(one,"Two");
t1.start();
t2.start();
}
}
执行结果与第2点相同,原因也一样
。如果将测试类做修改,修改为多线程处理不同的对象,执行结果第3点相同,原因也一样。其中this可以用private Object obj = new Object();obj替换
2)代码块在静态方法中
// 业务类
class Example {
// threadName 线程名称
public void executeOne(String threadName) {
synchronized (Example.class) {
for (int i = 0; i < 10; ++i) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + ": " + i);
}
}
}
}
// 控制类
class ThreadOne extends Thread {
private Example example;
private String threadName; // 线程名称。在多线程时以示区别
public ThreadOne(Example example, String threadName) {
this.example = example;
this.threadName = threadName;
}
public void run() {
this.example.executeOne(this.threadName);
}
}
// 测试类
public class ThradTest {
public static void main(String[] args) {
Example one = new Example();
Thread t1 = new ThreadOne(one,"One");
Thread t2 = new ThreadOne(one,"Two");
t1.start();
t2.start();
}
}
执行结果与第4点相同,
synchronized代码块是在静态方法中,该方法不属于one对象,是属于类Example。t1线程执行时,对Example类加锁,t2线程处于等待状态,等待t1释放锁,再执行。 其中Example.class可以用private static Object obj = new Object();的obj替换