Java 重新运行线程
在我的android游戏中,我正在生成一个单独的线程来播放Java 重新运行线程,java,android,multithreading,Java,Android,Multithreading,在我的android游戏中,我正在生成一个单独的线程来播放soundpool类的声音。每次我必须播放声音时,我必须创建一个新线程并执行thread.start()。是否可以一次性创建线程并重用?我希望这样做,以避免产生大量线程的开销 是否可以一次性创建线程并重用 这是不可能的 可能的解决方案是使用固定大小的线程池(取决于您的需求),并通过将可运行任务提交到线程池来继续重用它 确定线程池的完美大小很重要,太小会有类似的问题,太高会有性能问题。因此,您需要进行一些基准测试来确定相同的结果。一个更好的
soundpool
类的声音。每次我必须播放声音时,我必须创建一个新线程并执行thread.start()
。是否可以一次性创建线程并重用?我希望这样做,以避免产生大量线程的开销
是否可以一次性创建线程并重用
这是不可能的
可能的解决方案是使用固定大小的线程池(取决于您的需求),并通过将可运行任务提交到线程池来继续重用它
确定线程池的完美大小很重要,太小会有类似的问题,太高会有性能问题。因此,您需要进行一些基准测试来确定相同的结果。一个更好的想法是使其可配置并监视它
您可能想在java中了解线程池
是否可以一次性创建线程并重用
这是不可能的
可能的解决方案是使用固定大小的线程池(取决于您的需求),并通过将可运行任务提交到线程池来继续重用它
确定线程池的完美大小很重要,太小会有类似的问题,太高会有性能问题。因此,您需要进行一些基准测试来确定相同的结果。一个更好的想法是使其可配置并监视它
您可能想在java中了解线程池。您可以使用“ThreadPoolExecuter”
这是一个很好的例子:
您可以使用“ThreadPoolExecuter”
这是一个很好的例子:
您可以创建一个无限线程,使用
synchronized
、wait
和notify
命令,在每次触发时播放声音
class InfininteTriggerableThread extends Thread {
private volatile boolean paused = true;
private final Object pauseObject = new Object();
@Override
public void run(){
try {
while(true){
while (paused) {
synchronized(pauseObject) {
pauseObject.wait();
}
}
// do your action here
paused = true;
}
} catch (InterruptedException e) { }
}
// trigger method
public void trigger(){
paused = false;
synchronized(pauseObject) {
pauseObject.notify();
}
}
};
您可以使用
synchronized
、wait
和notify
命令创建一个无限线程,在每次触发时播放声音
class InfininteTriggerableThread extends Thread {
private volatile boolean paused = true;
private final Object pauseObject = new Object();
@Override
public void run(){
try {
while(true){
while (paused) {
synchronized(pauseObject) {
pauseObject.wait();
}
}
// do your action here
paused = true;
}
} catch (InterruptedException e) { }
}
// trigger method
public void trigger(){
paused = false;
synchronized(pauseObject) {
pauseObject.notify();
}
}
};
正如我之前承诺的那样,我测试了使用
Looper
无限运行的线程,并且可以接受Runnable
s逐个执行它们
// create a custom Thread class
class ThreadWorking extends Thread {
public volatile Handler handler;
@Override
public void run(){
// between Looper.prepare() and Looper.loop() we need to create a handler
// which will receive messages and runnables for this thread
Looper.prepare();
handler = new Handler();
Looper.loop();
}
};
// then create new thread and start it
final ThreadWorking threadWorking = new ThreadWorking();
threadWorking.start();
Log.println(Log.DEBUG, "thread test", "New thread started");
现在新线程正在循环,可以通过其处理程序接收消息
s和Runnable
s。它们将存储在内部队列中,并在这个特定线程中一个接一个地执行。要进行测试,请单击按钮发送Runnable
:
threadWorking.handler.post(new Runnable(){
@Override
public void run() {
try {
Log.println(Log.DEBUG, "thread test", "Executed: " + System.currentTimeMillis()/1000);
Thread.sleep(2000);
} catch (InterruptedException e) { }
}
});
在我启动一个应用程序并快速点击按钮数次后,日志显示:
04-09 16:21:56.599: D/thread test(19264): New thread started
04-09 16:21:59.569: D/thread test(19264): Executed: 1397046119
04-09 16:22:01.569: D/thread test(19264): Executed: 1397046121
04-09 16:22:03.569: D/thread test(19264): Executed: 1397046123
04-09 16:22:05.569: D/thread test(19264): Executed: 1397046125
04-09 16:22:07.569: D/thread test(19264): Executed: 1397046127
04-09 16:22:09.569: D/thread test(19264): Executed: 1397046129
因此,一切都按预期正常工作,没有冻结UI或创建额外线程。正如我之前承诺的那样,我测试了使用活套
无限运行的线程,并且可以接受可运行
一个接一个地执行它们
// create a custom Thread class
class ThreadWorking extends Thread {
public volatile Handler handler;
@Override
public void run(){
// between Looper.prepare() and Looper.loop() we need to create a handler
// which will receive messages and runnables for this thread
Looper.prepare();
handler = new Handler();
Looper.loop();
}
};
// then create new thread and start it
final ThreadWorking threadWorking = new ThreadWorking();
threadWorking.start();
Log.println(Log.DEBUG, "thread test", "New thread started");
现在新线程正在循环,可以通过其处理程序接收消息
s和Runnable
s。它们将存储在内部队列中,并在这个特定线程中一个接一个地执行。要进行测试,请单击按钮发送Runnable
:
threadWorking.handler.post(new Runnable(){
@Override
public void run() {
try {
Log.println(Log.DEBUG, "thread test", "Executed: " + System.currentTimeMillis()/1000);
Thread.sleep(2000);
} catch (InterruptedException e) { }
}
});
在我启动一个应用程序并快速点击按钮数次后,日志显示:
04-09 16:21:56.599: D/thread test(19264): New thread started
04-09 16:21:59.569: D/thread test(19264): Executed: 1397046119
04-09 16:22:01.569: D/thread test(19264): Executed: 1397046121
04-09 16:22:03.569: D/thread test(19264): Executed: 1397046123
04-09 16:22:05.569: D/thread test(19264): Executed: 1397046125
04-09 16:22:07.569: D/thread test(19264): Executed: 1397046127
04-09 16:22:09.569: D/thread test(19264): Executed: 1397046129
因此,在不冻结UI或创建额外线程的情况下,一切都能按预期正常工作。nope,一旦线程
终止,您需要创建一个新的线程
,以在线程
终止后重新运行可运行
逻辑,您需要创建一个新的线程
以重新运行可运行
逻辑如果您想知道处理器在运行(true)和(暂停)循环时是否会做不必要的工作,则不会。线程将暂停,直到同步对象变得可用。当您在调用等待后调用通知
时,对象将被通知已同步,线程将退出已同步
块。它将退出while(paused)
并继续执行,正如我在代码中的注释所示。实际上,这里不需要while(paused)
,您可以使用if(paused)
代替,但是while
是传统的且更健壮的方法。当然,只要修改触发器方法,使if paused==true,它将paused设置为false并调用notify,如果paused==false,则将它作为参数接收的某些对象(例如,您的声音)添加到队列中。所以在run()方法中,它应该查看队列并播放每一个声音,直到队列变为空。我找到了另一种运行无限线程的方法,以便它可以逐个接收和执行可运行线程。方法是运行Looper.prepare()
,然后创建一个处理程序,然后在这个新线程中运行Looper.loop()
,这样可以将可运行文件发送到这个特定的处理程序,并在它所连接的线程中执行,而不会丢失。明天,如果您想知道处理器在运行(true)和(pause)循环时是否会做不必要的工作,我将返回示例(我也对这个主题感兴趣)——不,不会。线程将暂停,直到同步对象变得可用。当您在调用等待后调用通知
时,对象将被通知已同步,线程将退出已同步
块。它将退出while(paused)
并继续执行,正如我在代码中的注释所示。实际上,这里不需要while(paused)
,您可以使用if(paused)
代替,但是while
是传统的且更健壮的方法。当然,只要修改触发器方法,使if paused==true,它将paused设置为false并调用notify,如果paused==false,则将它作为参数接收的某些对象(例如,您的声音)添加到队列中。所以在run()方法中,它应该查看队列并播放每一个声音,直到队列变为空。我找到了另一种运行无限线程的方法,以便它可以逐个接收和执行可运行线程。方法是运行Looper.prepare()
,