0

众所周知,只能同时运行一种同步方法。所以我的问题是,如果我将 run() 方法声明为同步,然后运行多线程,其他线程是否可以运行 run() 方法?像这样:

public Test extends Thread
{
    public synchronized void run()
       {...do something}

}
Test thread1 = new Test();
Test thread2 = new Test();
thread1.start();
thread2.start();

thread2 是否可以运行或 thread2 将等待 thread1 退出 run() 方法?

4

2 回答 2

4

实例方法上的synchronized关键字可防止在同一个实例上调用该方法时同时调用该方法。

尝试以下(1)

class SynchTest {
    public static void main(String[] args) {
        // Note that we create a new Task each time.
        new Thread(new Task()).start();
        new Thread(new Task()).start();
        new Thread(new Task()).start();
    }

    static class Task implements Runnable {
        long start;

        Task() {
            this.start = System.currentTimeMillis();
        }

        @Override
        public synchronized void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {
            }
            System.out.println(System.currentTimeMillis() - start);
        }
    }
}

这将输出如下内容:

1000
1001
1001

换句话说,每个任务自创建以来经过的时间约为 1 秒,这意味着它们可以同时运行。

现在尝试以下(2)

class SynchTest {
    public static void main(String[] args) {
        // Now we pass the same instance each time.
        Task t = new Task();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
    }

    static class Task implements Runnable {
        long start;

        Task() {
            this.start = System.currentTimeMillis();
        }

        @Override
        public synchronized void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {
            }
            System.out.println(System.currentTimeMillis() - start);
        }
    }
}

将同一个实例传递给所有 3 个线程意味着线程将尝试调用run同一个实例。这会输出如下内容:

1001
2001
3001

换句话说,每个任务都等待前一个任务。

如果你真的为每个对象synchronize全部,你可以指定你自己的监控对象(3)run

class SynchTest {
    public static void main(String[] args) {
        new Thread(new Task()).start();
        new Thread(new Task()).start();
        new Thread(new Task()).start();
    }

    static class Task implements Runnable {
        long start;

        Task() {
            this.start = System.currentTimeMillis();
        }

        static final Object STATIC_MONITOR = new Object();

        @Override
        public void run() {
            synchronized (STATIC_MONITOR) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ignored) {
                }
                System.out.println(System.currentTimeMillis() - start);
            }
        }
    }
}

即使我们每次都创建一个新任务,它的输出也与示例 2 相同。

另请参阅:您是否应该同步运行方法?为什么或者为什么不?

于 2013-10-30T17:32:09.050 回答
2

您创建了两个 Test 实例以及两个线程分别运行,因此其他线程不可能运行 run() 方法。仅当您的两个线程使用相同的实例运行时,如下所示:

class CustomTask implements Runnable {
    private int number;
    public synchronized void run() {
        while(!Thread.currentThread().isInterrupted()){
            System.out.println(Thread.currentThread().getName() + ": " + number);
            Thread.yield();
            ++number;
        }   
    }   
}

public class ThreadTest {
    public static void main(String... args) throws Exception {
        CustomTask ct = new CustomTask();
        ExecutorService exec = Executors.newCachedThreadPool();
        for(int i = 0; i < 2; i++){
            exec.execute(ct);
        }   
        TimeUnit.MILLISECONDS.sleep(1);
        exec.shutdownNow();    
    }   
}

run 方法需要一个 synchronized 关键字。

于 2019-01-05T03:54:31.770 回答