简体   繁体   中英

better way to interrupt thread Java

I have written a class in Java:

public class Main {
    public static boolean firstRunning = true;
    public static void main(String[] args) {
        (new Thread(){
            public void run(){
                secondFunction();
            }
        }).start();
        firstFunction();
    }

    public static void firstFunction()
    {
        for(int i = 0; i < 10 && firstRunning; i++)
        {
            try{Thread.sleep(1000);} catch(Exception e){}
            System.out.println("first - "+i);
        }
        return;
    }

    public static void secondFunction(){
        try{Thread.sleep(3000);} catch(Exception e){}
        firstRunning = false;
        for(int i = 0; i < 10; i++)
        {
            try{Thread.sleep(700);} catch(Exception e){}
            System.out.println("second - "+i);
        }
    }
}

I am calling the secondFuntion() in a new Thread after which I begin the execution of firstFuntion() in the Main Thread . After the execution of the Thread.sleep(3000) in the secondFuntion() , I want to make secondFunction() take over the Main Thread , for which I set the boolean flag firstRunning to false and cancel the execution of the Main Thread using the return statement.

This approach works for me, but is there a more elegant way of doing the same?

EDIT

The output of the code is

first - 0
first - 1
first - 2
second - 0
second - 1
second - 2
second - 3
second - 4
second - 5
second - 6
second - 7
second - 8
second - 9

If you just want to make the main thread exit, then this is the most simple way to do it.

But usually, you have more complex / different needs. My guess is that you try to solve a different problem and this was your first solution. Unless you tell us about your original problem, we can't tell you what a good solution would be.

If you just want 2 threads to share something (ie not use it at the same time), you can use a lock (see Java 7 docs ).

Pseudocode:

  • Main thread creates the lock
  • Main thread creates second thread and passes the lock to it
  • First function tries to acquire lock inside of the loop. When it suceeds, it runs the loop body once and releases the lock.
  • Thread 2 then uses the lock to make sure the main thread blocks while it does its work

In my opinion there is no need to actively wait. A more elegant approach is to use a CountDownLatch for this specific problem. If you want the main thread to wait until an other thread did perform an operation, you could for exmple use a CountDownLatch like this:

public class Main {
   private static final CountDownLatch latch = new CountDownLatch(1);
   public static void main(String[] args) throws InterruptedException {
       (new Thread(){
           public void run(){
               secondFunction();
           }
       }).start();
       firstFunction();
       System.out.println("DONE!");
   }

    public static void secondFunction(){
        latch.await(); // blocks the main thread here until 
                       // the latch has been counted down to 0
    }

   public static void secondFunction(){
       System.out.println("secondFunction 1");
       try{Thread.sleep(3000);} catch(Exception e){}
       System.out.println("secondFunction 2");
       latch.countDown(); // this counts down the latch from 1 to 0 and
                          // releases the initial thread from blocking
       // ... continue with some other operations
   }

Output:

secondFunction 1
secondFunction 2
DONE!

Have a look at the Java documentation for more details. An alternative to this approach and the "standard" way of solving thread waiting problems in Java is the so called "monitor" concept using synchronize/wait/notify. Have a look at this stackoverflow post for an example.

As your real problem is not clear from the question, just to achieve your output you can use the following code. It uses the synchronization, wait/notify functionality given by Threads in java:

public class Main {
    private static Thread t1;
    private static Object lock = new Object();//dummy object to perform sychronization
    public static void main(String[] args) {
        t1 = new Thread(){
            public void run(){
                secondFunction();
            }
        };
        t1.start();
        firstFunction();
    }

    public static void firstFunction()
    {
        for(int i = 0; i < 10; i++)
        {
            if(i == 3){
                 synchronized (lock) { // wait till the lock is available 
                    try {
                        lock.wait(); // wait till some thread notifies
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            try{Thread.sleep(1000);} catch(Exception e){}
            System.out.println("first - "+i);
        }
        return;
    }

    public static void secondFunction(){
        try{Thread.sleep(3000);} catch(Exception e){} //wait for 3 sec to run the main thread 3 times
        synchronized (lock) { //aquire the lock
             for(int i = 0; i < 10; i++)
             {
                 try{Thread.sleep(700);} catch(Exception e){}
                 System.out.println("second - "+i);
             }
               //don't notify the main thread that this thread is done with lock
        }
    }
}

As the code is not notifying that "lock" is no more in use through second function and the new thread, the main thread will keep on waiting for the notification.

Output is same as given in question.

Warning: This is not the good way to use lock and synchronization but just to give you an example of how threads lock/synchronization can be used. Had your real problem been clear, We would have decided the best approach for it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM