-1

我有以下用例。假设它将在 JAVA 6 上运行,任何人都可以建议方法t1()的良好实现吗?我试图考虑使用 wait() 和 notify() 来完成此操作,但无法获得适当的解决方案。任何帮助将不胜感激。(请注意,这两个方法t1()m1()都将在不同的线程中调用)

 class Test
 {

   static volatile int flag = 0;

   public static void t1()
   {
           //This method will be called in a Thread called T2
           /*This method must wait for flag to become 1. As soon it
             becomes 1 this must return. However it should wait for maximum 
             n seconds. After that even if flag is 0 it must return.*/
   }



   public static void m1()
   {
           //This method will be called in a Thread called T1
           flag = 1;
   }
} 

到目前为止,这是我尝试执行的 t1()

   public static void t1() throws InterruptedException
   {
          while(flag == 0)
          {
               Thread.currentThread().sleep(100);
          }
   }

以上工作,但问题是没有实现超时,while循环似乎不是那么好。

4

4 回答 4

3

使用CountDownLatch. 在计数为一的任何线程运行之前对其进行初始化。然后,您的代码将如下所示:

class Test
 {

   static CountDownLatch latch = new CountDownLatch(1);

   public static void t1()
   {
           //This method will be called in a Thread called T2
           /*This method must wait for flag to become 1. As soon it
             becomes 1 this must return. However it should wait for maximum 
             n seconds. After that even if flag is 0 it must return.*/
           latch.await(1L,TimeUnit.SECONDS);
           //your remaining logic
   }



   public static void m1()
   {
          //your logic
          latch.countDown();
   }
}

ACountDownLatch是信号量的一些修改、增强(例如超时选项)并且可以说更容易理解的实现——信号量是广泛用于跨多种语言(不仅是 Java)的线程同步的基本结构之一。在将 Wikipedia 参考与 Java 实现进行比较时,请注意以下几点:

  • P/wait()对应于await(),不同之处await()不会改变count值。
  • V/signal()对应于countDown(),区别在于countDown()倒计时,而不是倒计时(显然)。
于 2013-08-26T17:28:02.303 回答
2

用一个CountDownLatch

private static CountDownLatch countDownLatch = new CountDownLatch(1);

public static void t1() throws InterruptedException {
    countDownLatch.await(1000L, TimeUnit.MILLISECONDS);
    System.out.println("t2");
}

public static void m1() throws InterruptedException {
    System.out.println("t1");

    // you can simulate some activity
    Thread.sleep(500);
    countDownLatch.countDown();
}

运行的线程t1()将不得不等待一秒钟。

public static void main(String[] args) throws IOException, ParseException {
    Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                test.Test.m1();
            } catch (InterruptedException e) {
                // do something
            }
        }
    });

    Thread t2 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                test.Test.t1();
            } catch (InterruptedException e) {
                // do something
            }
        }
    });
    t2.start();
    t1.start();
}

这在静态上下文中是个坏主意,因为其他类可以访问它并可能调用方法,这会搞砸闩锁。

于 2013-08-26T17:27:19.257 回答
0

您可以轮询直到满足条件。而不是Thread.sleep(long time)在检查之间使用,我认为只使用更实用Thread.yield()

public static void t1()
{
    while (flag == 0)
    {
        Thread.yield();
    }
}
于 2013-08-26T17:31:23.937 回答
0

叙述完整的例子使用CountDownLatch

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class Race {

    public static void main(String[] args) {
        boolean flag=true; //set false to see other behavior
        if (flag) {
            startRace(5L, 2L);
        } else {
            startRace(2L, 5L);
        }
    }

    private static void startRace(final long s1, final long s2) {
        new Thread() {
            @Override
            public void run() {
                Test.t1(s1);
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                Test.t2(s2);
            }
        }.start();
    }
}

class Test {

    static volatile int flag = 0;

    static CountDownLatch L = new CountDownLatch(1);

    public static void t1(long n) {
        await(n);
        logic1();
        L.countDown(); // comment to wait till end

    }

    public static void t2(long n) {
        await(n);
        logic2();
        L.countDown();
    }

    private static void logic1() {
        if (flag == 0) {
            System.out.println(Thread.currentThread()
                    + ": Flag Couldnt be set in time");
        } else {
            System.out.println(Thread.currentThread() + ": Flag set in time");
        }
    }

    private static void logic2() {
        flag = 1;
        System.out.println(Thread.currentThread() + ": Flag Set");
    }

    private static void await(long n) {
        waitMsg(n);
        try {
            if (L.await(n, TimeUnit.SECONDS)) {
                waitOverBefore(n);
            } else {
                waitOver(n);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private static void waitOverBefore(long n) {
        System.out.println(Thread.currentThread() + ": Waiting Over before "
                + n + " seconds");
    }

    private static void waitOver(long n) {
        System.out.println(Thread.currentThread() + ":" + n
                + " seconds Waiting Over");
    }

    private static void waitMsg(long n) {
        System.out.println(Thread.currentThread() + ":Waiting for " + n
                + " seconds");
    }

}

输出 1

Thread[Thread-0,5,main]:Waiting for 5 seconds
Thread[Thread-1,5,main]:Waiting for 2 seconds
Thread[Thread-1,5,main]:2 seconds Waiting Over
Thread[Thread-1,5,main]: Flag Set
Thread[Thread-0,5,main]: Waiting Over before 5 seconds
Thread[Thread-0,5,main]: Flag set in time

输出 2

Thread[Thread-1,5,main]:Waiting for 5 seconds
Thread[Thread-0,5,main]:Waiting for 2 seconds
Thread[Thread-0,5,main]:2 seconds Waiting Over
Thread[Thread-0,5,main]: Flag Couldnt be set in time
Thread[Thread-1,5,main]: Waiting Over before 5 seconds
Thread[Thread-1,5,main]: Flag Set
于 2013-08-26T18:22:37.390 回答