当无涯教程在程序中启动两个或多个线程时,可能会出现多个线程尝试访问同一资源,最终由于并发问题,它们可能产生无法预料的情况。如果多个线程试图在同一文件中写入数据,则它们可能会破坏数据,因为其中一个线程可以覆盖数据,或者当一个线程打开同一文件时,另一个线程可能正在关闭同一文件。
Java编程语言提供了一种非常方便的方法,可以通过使用 synchronized 块来创建线程并同步其任务,以下是同步语句的一般形式-
synchronized(objectidentifier) { //Access shared variables and other shared resources }
在这里, objectidentifier 是对对象的引用,该对象 的锁与同步语句表示的监视器相关联。
未同步多线程示例
这是一个简单的示例,它可以按顺序打印计数器值,也可以不按顺序打印,并且每次运行它时,它的输出值都不一样。
class PrintDemo {
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
threadName = name;
PD = pd;
}
public void run() {
PD.printCount();
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
</span><span class="typ">PrintDemo</span><span class="pln"> PD </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">PrintDemo</span><span class="pun">();</span><span class="pln">
</span><span class="typ">ThreadDemo</span><span class="pln"> T1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ThreadDemo</span><span class="pun">(</span><span class="pln"> </span><span class="str">"Thread - 1 "</span><span class="pun">,</span><span class="pln"> PD </span><span class="pun">);</span><span class="pln">
</span><span class="typ">ThreadDemo</span><span class="pln"> T2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ThreadDemo</span><span class="pun">(</span><span class="pln"> </span><span class="str">"Thread - 2 "</span><span class="pun">,</span><span class="pln"> PD </span><span class="pun">);</span><span class="pln">
T1</span><span class="pun">.</span><span class="pln">start</span><span class="pun">();</span><span class="pln">
T2</span><span class="pun">.</span><span class="pln">start</span><span class="pun">();</span><span class="pln">
</span><span class="com">//wait for threads to end</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
T1</span><span class="pun">.</span><span class="kwd">join</span><span class="pun">();</span><span class="pln">
T2</span><span class="pun">.</span><span class="kwd">join</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="typ">Exception</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Interrupted"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
}
}
每次您运行该程序时,都会产生不同的输出-
Starting Thread - 1 Starting Thread - 2 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 5 Counter --- 2 Counter --- 1 Counter --- 4 Thread Thread - 1 exiting. Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting.
同步多线程示例
这是相同的示例,它按顺序打印计数器值,并且每次运行它时,它都会产生相同的输出。
class PrintDemo {
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
threadName = name;
PD = pd;
}
public void run() {
synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
</span><span class="typ">ThreadDemo</span><span class="pln"> T1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ThreadDemo</span><span class="pun">(</span><span class="pln"> </span><span class="str">"Thread - 1 "</span><span class="pun">,</span><span class="pln"> PD </span><span class="pun">);</span><span class="pln">
</span><span class="typ">ThreadDemo</span><span class="pln"> T2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ThreadDemo</span><span class="pun">(</span><span class="pln"> </span><span class="str">"Thread - 2 "</span><span class="pun">,</span><span class="pln"> PD </span><span class="pun">);</span><span class="pln">
T1</span><span class="pun">.</span><span class="pln">start</span><span class="pun">();</span><span class="pln">
T2</span><span class="pun">.</span><span class="pln">start</span><span class="pun">();</span><span class="pln">
</span><span class="com">//wait for threads to end</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
T1</span><span class="pun">.</span><span class="kwd">join</span><span class="pun">();</span><span class="pln">
T2</span><span class="pun">.</span><span class="kwd">join</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="typ">Exception</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Interrupted"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
}
}
每次您运行该程序时,都会产生相同的输出-
Starting Thread - 1 Starting Thread - 2 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 1 exiting. Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting.