双线程Java多线程同步方法
我有一个非常简单的代码,但无法理解双线程Java多线程同步方法,java,multithreading,synchronized,Java,Multithreading,Synchronized,我有一个非常简单的代码,但无法理解 public class Test extends Thread { public synchronized void testPrint() { System.out.println("I am sleeping..." + Thread.currentThread().getName()); try {
public class Test extends Thread {
public synchronized void testPrint() {
System.out.println("I am sleeping..."
+ Thread.currentThread().getName());
try {
Thread.sleep(3000);
System.out.println("I am done sleeping..."
+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
Test t = new Test();
t.testPrint();
System.out.println("I am out..." + Thread.currentThread().getName());
}
public static void main(String[] args) {
Test t1 = new Test();
Test t2 = new Test();
t1.start();
t2.start();
}
}
这是我的问题
当两个线程执行Test t=new Test()
时,是否会创建两个同名的不同对象?多线程的这一行发生了什么?
我的成绩不理想
我正在睡觉…线程0
我在睡觉……一号线
我睡不着了…线程0
我出局了……0号线
我已经睡不着了…一号线
我出局了…一号线
从输出来看,这肯定意味着创建了两个对象,这就是为什么两个线程都可以进入sync方法。希望我的理解是正确的?
系统如何维护这两个对象?您正在创建两个不同的对象,这两个对象将有两个不同的监视器,在这两个监视器上将获取锁。由于两个线程都在不同的对象上工作,所以无法实现同步 你可以试试
public class Test extends Thread {
Object obj;
public Test(Object obj){
this.obj = obj;
}
public synchronized void testPrint() {
System.out.println("I am sleeping..."
+ Thread.currentThread().getName());
try {
Thread.sleep(3000);
System.out.println("I am done sleeping..."
+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
((Test)obj).testPrint();
System.out.println("I am out..." + Thread.currentThread().getName());
}
public static void main(String[] args) {
Object obj = new Test(null);
Test t1 = new Test(obj);
Test t2 = new Test(obj);
t1.start();
t2.start();
}
}
输出是
I am sleeping...Thread-1
I am done sleeping...Thread-1
I am out...Thread-1
I am sleeping...Thread-2
I am done sleeping...Thread-2
I am out...Thread-2
正如预期的那样。您正在创建两个不同的对象,这两个对象将有两个不同的监视器,将在其上获取锁。由于两个线程都在不同的对象上工作,所以无法实现同步 你可以试试
public class Test extends Thread {
Object obj;
public Test(Object obj){
this.obj = obj;
}
public synchronized void testPrint() {
System.out.println("I am sleeping..."
+ Thread.currentThread().getName());
try {
Thread.sleep(3000);
System.out.println("I am done sleeping..."
+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
((Test)obj).testPrint();
System.out.println("I am out..." + Thread.currentThread().getName());
}
public static void main(String[] args) {
Object obj = new Test(null);
Test t1 = new Test(obj);
Test t2 = new Test(obj);
t1.start();
t2.start();
}
}
输出是
I am sleeping...Thread-1
I am done sleeping...Thread-1
I am out...Thread-1
I am sleeping...Thread-2
I am done sleeping...Thread-2
I am out...Thread-2
正如预期的那样。当您运行
Test t=new Test()
jvm在堆上创建新对象,并将带有指向该对象链接的变量t放在当前线程的堆栈上。当您在两个或多个不同的线程中运行该代码时,每个线程都有自己的堆栈,因此当您运行
Test t=new Test()
jvm在堆上创建新对象并将带有指向该对象链接的变量t放在当前线程的堆栈上时,每个线程都会创建自己的变量t和对象Test。Test t = new Test()
当您在两个或多个不同线程中运行该代码时,每个线程都有自己的堆栈,因此每个线程都创建自己的变量t和对象Test
Test t = new Test()
这将在堆中创建一个对象,引用将放置在堆栈中
在您的示例中,您根本不需要synchronized
方法,因为您没有在不同的线程之间共享实例
这将在堆中创建一个对象,引用将放置在堆栈中
在您的示例中,您根本不需要
synchronized
方法,因为您没有在不同的线程之间共享实例。使用当前方法,您可以确保对于Test
的每个实例,方法testPrint()
不能同时运行。这完全取决于你想做什么。我假设您希望保护testPrint()
方法,使其不在多个线程中同时运行,同时使用Test
的多个实例
目前,您直接在方法上使用synchronized
关键字。这将导致使用对象本身(测试的一个实例)进行同步
您应该在Test
实例之间共享的另一个对象上进行同步(例如,您可以使锁对象成为静态的)
另外请注意,通常最好只实现Runnable
接口,然后将实现传递给线程。
另外,您不必每次运行时都创建一个新的Test
实例(我看不出这样做的目的),我对此进行了注释
public class Test extends Thread {
// could also use a static monitor instead.
// private static final Object monitor = new Object();
private final Object monitor;
public Test(final Object monitor) {
this.monitor = monitor;
}
public void testPrint() {
synchronized (monitor) {
System.out.println("I am sleeping..." + Thread.currentThread().getName());
try {
Thread.sleep(3000);
System.out.println("I am done sleeping..." + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void run() {
//Test t = new Test(monitor);
//t.testPrint();
testPrint();
System.out.println("I am out..." + Thread.currentThread().getName());
}
public static void main(String[] args) {
// synchronization will happen on this object.
final Object monitor = new Object();
Test t1 = new Test(monitor);
Test t2 = new Test(monitor);
t1.start();
t2.start();
}
}
使用当前方法,可以确保对于
Test
的每个实例,方法testPrint()
不能同时运行。这完全取决于你想做什么。我假设您希望保护testPrint()
方法,使其不在多个线程中同时运行,同时使用Test
的多个实例
目前,您直接在方法上使用synchronized
关键字。这将导致使用对象本身(测试的一个实例)进行同步
您应该在Test
实例之间共享的另一个对象上进行同步(例如,您可以使锁对象成为静态的)
另外请注意,通常最好只实现Runnable
接口,然后将实现传递给线程。
另外,您不必每次运行时都创建一个新的Test
实例(我看不出这样做的目的),我对此进行了注释
public class Test extends Thread {
// could also use a static monitor instead.
// private static final Object monitor = new Object();
private final Object monitor;
public Test(final Object monitor) {
this.monitor = monitor;
}
public void testPrint() {
synchronized (monitor) {
System.out.println("I am sleeping..." + Thread.currentThread().getName());
try {
Thread.sleep(3000);
System.out.println("I am done sleeping..." + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void run() {
//Test t = new Test(monitor);
//t.testPrint();
testPrint();
System.out.println("I am out..." + Thread.currentThread().getName());
}
public static void main(String[] args) {
// synchronization will happen on this object.
final Object monitor = new Object();
Test t1 = new Test(monitor);
Test t2 = new Test(monitor);
t1.start();
t2.start();
}
}
这里两个线程将进入运行,这将创建两个对象还是一个对象?如果它在两个各自的线程中创建两个对象,我如何在后续代码中使用这两个对象?i、 e.两个对象都有相同的名称“t”!或者范围仅在这些线程中?如果线程共享内存,那么其他线程和主线程应该可以访问这些对象。。那我怎么用呢?如果它只创建一个具有2个引用的对象,那么两个线程不应该同时进入该方法。。正确的?但输出显示的情况并非如此。有两个对象,但没有从其他代码链接到它们。在java中,您不能直接访问内存-您应该将指向对象的链接保存在变量或属性中。当你们将链接保存到变量时,它不能从其他线程访问,当在属性中时,它可以被访问。好的,谢谢,我想我得到了。唯一的问题是,如果我在代码中使用't'对象,那么它将引用哪个对象?由线程1或线程2创建?我如何知道创建了哪些对象,因为对象的状态可能不同。此代码是一个缺陷吗?在您的代码中,您使用了在
current
线程中创建的对象。这不是缺陷本身,它取决于您的目标。两个线程将进入运行,这将创建两个对象还是一个?如果它在两个各自的线程中创建两个对象,我如何在后续代码中使用这两个对象?i、 e.两个对象都有相同的名称“t”!或者范围仅在这些线程中?如果线程共享内存,那么其他线程和主线程应该可以访问这些对象。。那我怎么用呢?如果它只创建一个o