Java 如何区分已锁定到不同实例的线程?
我了解到线程可以锁定“资源”,比如说他们正在使用的对象,这样一次只允许一个线程使用和修改它,这就是同步问题。我创建了一个类的两个不同实例,并将其提供给我的线程,试图确保它们锁定在不同的“资源”上。他们是如何表现得好像锁定了相同的资源?我很困惑,因为我没有任何关于线程的经验和知识 这是我从在线教程中修改的代码,以尝试我所想的:Java 如何区分已锁定到不同实例的线程?,java,multithreading,thread-synchronization,Java,Multithreading,Thread Synchronization,我了解到线程可以锁定“资源”,比如说他们正在使用的对象,这样一次只允许一个线程使用和修改它,这就是同步问题。我创建了一个类的两个不同实例,并将其提供给我的线程,试图确保它们锁定在不同的“资源”上。他们是如何表现得好像锁定了相同的资源?我很困惑,因为我没有任何关于线程的经验和知识 这是我从在线教程中修改的代码,以尝试我所想的: public class TestThread { public static void main(String args[]) {
public class TestThread {
public static void main(String args[]) {
PrintDemo PD1 = new PrintDemo("No.1"); //just prints from 1 to 5
PrintDemo PD2 = new PrintDemo("No.2");
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD1 );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD2 );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("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 ();
}
}
}
class PrintDemo {
private String name;
PrintDemo(String name) {
this.name = name;
}
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println(name + " Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
每次跑步都应该有所不同,但总是一样的:
输出:
Starting Thread - 1
Starting Thread - 2
No.1 Counter --- 5
No.1 Counter --- 4
No.1 Counter --- 3
No.1 Counter --- 2
No.1 Counter --- 1
Thread Thread - 1 exiting.
No.2 Counter --- 5
No.2 Counter --- 4
No.2 Counter --- 3
No.2 Counter --- 2
No.2 Counter --- 1
Thread Thread - 2 exiting.
起始线程-1
起始线程-2
1号柜台——5号
1号柜台--4号
1号柜台--3号
1号柜台--2号
1号柜台--1号
线程-1正在退出。
2号柜台——5号
2号柜台--4号
2号柜台--3号
2号柜台--2号
2号柜台--1号
线程-2退出。
编辑#1:我按照你的要求填写了整个代码。我还测试了代码,没有覆盖start。结果是一样的。如果添加
线程。睡眠(1000)
在PrintDemo的每个刻度之间,您可能会看到两个线程都执行5、4、3等操作。现在第一个线程速度太快,它完成的速度比主线程启动第二个线程的速度快
同步在这里没有效果,两个线程在不同的资源上同步,这没有效果。在证明(使用Thread.sleep)两个线程同时执行之后,然后在共享对象上添加同步,即使等待,两个线程也会一个接一个地完全执行。问题在于
ThreadDemo.start()
方法
您的ThreadDemo
类是用extends-Thread
声明的,但您从未将其实际用作线程。相反,真正的线程对象是在ThreadDemo.start()中创建的
以下是可能发生的情况:
主线程调用T1.start()
。它创建一个新线程,这需要一些时间,然后启动线程
T2.start()
T2.start()
会创建另一个新线程,这需要一些时间。与此同时,另一条线仍在打印。它不会打印太多的行,而且system.out
是缓冲的,所以很有可能,它能够在任何实际I/O发生之前打印所有行。同时T2
线程。这需要一些时间T2
线程,该线程打印其五行,然后…故事结束了。这就是它可能下降的原因。您多久运行一次代码?两次输出相同是完全可能的,2000次仍然是可能的,但可能性更大。也许不要打印5次,而是打印1000次,以便给线程更多的发散时间。为什么要重写
start()
方法?躲在那里的是什么?重写start()
非常不寻常。不要扩展线程
,而是实现可运行
。重写Thread.start()
可能会导致问题,这会阻止Thread
在单独的线程中实际运行。不要这样做。顺便说一句,两条线打印的线的交错不是每次都不同。只是情况可能不同而已。我知道第一个线程总是在第二个线程开始之前运行到完成,这有点可疑,但仅此而已--可疑--这并不能证明Java运行时或操作系统有任何问题。@SolomonSlow我编辑了这篇文章,以便您可以看到它是什么。我也试过了,但没有覆盖开始。同样的结果
t = new Thread (this, threadName);
t.start ();