代码有什么问题,我的线程没有得到同步: 我有以下示例同步打印方法,该线程会调用但仍然输出显示线程在访问print方法时不同步。见下面的输出。
主要类
public class ExecutorTester {
public static void main(String[] args) {
PrinterRunnable pr = new PrinterRunnable();
ExecutorService excutor = Executors.newFixedThreadPool(20);
//ExecutorService excutor = Executors.newSingleThreadExecutor();
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.shutdown();
for(int i =0; i<5;i++)
System.out.println("In Main Thread : "+i);
}
}
主题类
public class PrinterRunnable implements Runnable {
@Override
public void run() {
for(int i =0; i<5;i++){
//System.out.println("In Thread class" +i);
Printer p = new Printer();
p.print(i);
}
}
}
其他课程
public class Printer {
public synchronized void print(int i){
System.out.println("Entered Thread: "+Thread.currentThread().getId());
System.out.println("In thread: "+Thread.currentThread().getId()+"count::"+i );
System.out.println("Exit Thread: "+Thread.currentThread().getId());
}
}
控制台输出 (见下面的第13和11号线都已输入!!!)
Entered Thread: 13
Entered Thread: 11
In thread: 11count::0
Exit Thread: 11
Entered Thread: 11
In thread: 11count::1
Exit Thread: 11
In thread: 13count::0
Exit Thread: 13
Entered Thread: 13
In thread: 13count::1
Exit Thread: 13
........
........
........
答案 0 :(得分:3)
当关键字synchronized
是方法签名的一部分时,就像在
public synchronized void print(int i)
然后此同步指的是调用此方法的实例。每次要打印时,您都要创建一个新的Printer
实例。
为了达到预期的效果,您必须在一个公共对象上进行同步。例如,这可以像这样实现:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorTester
{
public static void main(String[] args)
{
PrinterRunnable pr = new PrinterRunnable(new Object());
ExecutorService excutor = Executors.newFixedThreadPool(20);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.submit(pr);
excutor.shutdown();
for (int i = 0; i < 5; i++)
System.out.println("In Main Thread : " + i);
}
}
class PrinterRunnable implements Runnable
{
private final Object monitor;
PrinterRunnable(Object monitor)
{
this.monitor = monitor;
}
@Override
public void run()
{
for (int i = 0; i < 5; i++)
{
// System.out.println("In Thread class" +i);
Printer p = new Printer(monitor);
p.print(i);
}
}
}
class Printer
{
private final Object monitor;
Printer(Object monitor)
{
this.monitor = monitor;
}
public void print(int i)
{
synchronized (monitor)
{
System.out.println("Entered Thread: " +
Thread.currentThread().getId());
System.out.println("In thread: " +
Thread.currentThread().getId() + " count::" + i);
System.out.println("Exit Thread: " +
Thread.currentThread().getId());
}
}
}
但当然,这是一个过于务实的草图。在您的实际应用程序中,您应该仔细考虑要强制同步的哪个对象。
答案 1 :(得分:1)
在这个位置:
@Override
public void run() {
for(int i =0; i<5;i++){
//System.out.println("In Thread class" +i);
Printer p = new Printer();
p.print(i);
}
}
每个线程都为每次迭代创建自己的打印机。同步的工作原理是阻止其他线程对同一对象执行同步方法,直到一个线程完成其synchronized方法。根据:https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
答案 2 :(得分:0)
synchronized
方法是对象的每个实例,并且在创建多个实例时没有争用。根据您的要求,您可以将方法更改为static
或同步类变量。
答案 3 :(得分:0)
他们当然是同步的。每个人都有自己的监视器,与它自己的Printer对象有关。 由于您要创建5个不同的打印机对象,&#34;同步&#34;在不同的对象上执行,永远不会锁定执行过程。
您应创建一个对象并将其用于同步。 例如:
public class Printer {
public void print(int i){
syncrhonized(Printer.class) {
System.out.println("Entered Thread: "+Thread.currentThread().getId());
System.out.println("In thread: "+Thread.currentThread().getId()+"count::"+i );
System.out.println("Exit Thread: "+Thread.currentThread().getId());
}
}
}
因为只有一个Printer.class对象,所以它们将始终同步。