如何实现真正的异步java线程

时间:2010-04-20 16:08:19

标签: java multithreading asynchronous runnable

我有一个需要执行两个操作的函数,一个快速完成,另一个需要很长时间才能运行。我希望能够将长时间运行的操作委托给一个线程,我不在乎线程何时完成,但线程需要完成。我实现了如下所示,但是,我的第二次操作永远不会完成,因为函数在start()调用之后退出。我如何确保函数返回但第二个操作线程也完成其执行并且不依赖于父线程?

public void someFunction(String data)
{
   smallOperation()
   SecondOperation a = new SecondOperation();
   Thread th = new Thread(a);
   th.Start();
}

class SecondOperation implements Runnable
{
  public void run(){
  // doSomething long running
 }
} 

8 个答案:

答案 0 :(得分:39)

public void someFunction(final String data) {
    shortOperation(data);
    new Thread(new Runnable() {
        public void run(){
            longOperation(data);
        }
    }).start();
}

如果调用someFunction,JVM将运行longOperation if

  1. 运行它的线程未标记 作为守护进程(在上面的代码中 不是)
  2. longOperation()不会抛出异常并且
  3. longOperation()
  4. 中没有调用System.exit()

答案 1 :(得分:1)

在线程终止之前,JVM不会退出。您发布的此代码甚至无法编译;也许问题在于你的实际代码。

答案 2 :(得分:1)

如果你的第二个功能没有完成,它与你的函数返回无关。如果某些内容调用System.exit()或者您的函数抛出异常,则该线程将停止。否则,即使主线程停止,它也会一直运行直到完成。可以通过将新线程设置为守护进程来防止这种情况,但是你没有在这里做到这一点。

答案 3 :(得分:1)

从 Java 1.8 开始,您可以非常简单地运行异步代码。下一段代码见:

audio_path = '/Volumes/EwhitePhD/hawaiianotate' 
os.chdir(audio_path)

cmap = cm.get_cmap('viridis')
genres = 'AmbientNoise Biological Clicks Delphinid VesselNoise'.split()
for g in genres:
    pathlib.Path(f'img_data/{g}').mkdir(parents=True, exist_ok=True)
    for filename in os.listdir(f'/Volumes/EWhite/genres/{g}'):
        if filename.startswith("._")
            songname = f'/Volumes/EWhite/genres/{g}/{filename}'
            y, sr = librosa.load(songname, sr=96000, duration=3)
            Y = librosa.amplitude_to_db(y, ref=np.max)
            plt.Figure(figsize=(8,8))
            plt.specgram(Y, NFFT=4096, Fs=sr, window=window_hamming noverlap=2048, cmap=cmap, sides='default', mode='default', scale='dB');
            plt.axis('off');
            plt.savefig(f'img_data/{g}/{filename.replace(".wav","")}.png', dpi=400)
            plt.clf()

答案 4 :(得分:0)

使用现代 Java

的解决方案
public void someFunction(String data) {
    smallOperation();
    new Thread(() -> {
        // doSomething long running
    }).start();
}

答案 5 :(得分:0)

回答这个问题可能为时已晚,但这是可行的解决方案。 只需将可运行对象添加到ExecutorService。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

ExecutorService executor = Executors.newFixedThreadPool(10);
        executor.execute(new Runnable() {
            @Override
            public void run() {
                //your code
            }
        });

答案 6 :(得分:0)

如果我的问题正确无误,则您想调用someFunction(),执行简短的smallOperation(),向SecondOperation运行一个线程,并确保从此函数返回时,{ {1}}完成。

如果我建议的流程正确,那么您只需添加以下行:

SecondOperation

看一下这个article,它指出:“当我们在线程上调用join()方法时,调用线程进入等待状态。它保持等待状态,直到引用线程终止“。我认为您想要实现的目标

如果不是这种情况,并且您想在public void someFunction(String data) { smallOperation() SecondOperation a = new SecondOperation(); Thread th = new Thread(a); th.Start(); th.join(); //add this line to make your MainThread await for this to finish . } class SecondOperation implements Runnable { public void run(){ // doSomething long running } } 终止时收到通知,建议您使用asyncTask

答案 7 :(得分:-1)

通过在临时线程中创建第二个线程来创建一个真正的异步线程。

{{1}}