在Android Studio中,我有一个包含在类似方法中的线程(如下所示),因为我想在调用时重新启动线程 [1],(重新创建线程而不是重新启动)
public void callthread(){
final Thread myThread = new Thread(new Runnable()
{
@Override
public void run()
{
for (int x=0; x<750&&!Thread.interrupted(); x++) {
//using this and thread sleep for repeated timed code within a thread
try {
Thread.sleep(4);
runOnUiThread(new Runnable()
{
@Override
public void run() {
//some code
if (condition) {
myThread.interrupt();
}
}
});
} catch (InterruptedException e) {
}
}
}
});
我的问题是它不允许我在我的代码中的所需位置使用myThread.interrupt();
,给我一个错误,说“变量'myThread'可能尚未初始化”并且因此不会编译。但是,当整个线程包含在类中但它没有办法重新启动时,它可以工作。换句话说,我需要一种在线程包含在方法中时中断线程的方法。 [2]
接受的解决方案
[1]。 可以重新启动线程的解决方案
[2]。 线程可以在线程包含在方法中时被中断的解决方案
PS:如果不清楚,我已经编辑了上面的代码以便于阅读,但我没有删除像for
循环或Thread.sleep
这样的内容,因为我认为它们可能是问题的一部分。因此,如果某个大括号中的太多或太少,那么这不是问题
编辑:搜索一下,显然你不能重新开始一个线程
答案 0 :(得分:2)
在进入for循环之前,您可以在myThread
中启动中断线程。中断线程休眠5秒,然后中断myThread
。中断在异常处理程序中处理。循环变量x
重置为0
,这实际上是循环的重启。
public class ThreadInterruptRestart {
public static void main(String[] args) {
new ThreadInterruptRestart().callthread();
}
public void callthread() {
final Thread myThread = new Thread("myThread") {
@Override
public void run() {
final Thread _this = this;
Thread interruptingThread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// this is not the interrupt we are interested in
e.printStackTrace();
}
if (true) {
System.out.println("interrupting " + _this + " from thread " + this);
_this.interrupt();
}
}
}, "interrupting thread");
interruptingThread.start();
for (int x = 0; x < 750; x++) {
// using this and thread sleep for repeated timed code
// within a thread
try {
System.out.println(x);
Thread.sleep(10);
} catch (InterruptedException e1) {
// this is the interrupt we want to handle
System.out.println("" + this + " interrupted!");
// reset the loop counter
x = 0;
}
}
}
};
myThread.start();
}
}
另一个myThread
没有睡眠的版本,而是使用同步代替InterruptedException
:
public class ThreadInterruptRestart {
public static void main(String[] args) {
new ThreadInterruptRestart().callthread();
}
public void callthread() {
final Object mutex = new Object();
final Thread myThread = new Thread("myThread") {
@Override
public void run() {
final Thread _this = this;
Thread interruptingThread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// this is not the interrupt we are interested in
e.printStackTrace();
}
if (true) {
System.out.println("interrupting " + _this + " from thread " + this);
synchronized (mutex) {
_this.interrupt();
}
}
}
}, "interrupting thread");
interruptingThread.start();
for (int x = 0; x < 75000; x++) {
// using this and thread sleep for repeated timed code
// within a thread
synchronized (mutex) {
System.out.println(x);
// do other stuff here
}
if (Thread.interrupted()) {
// this is the interrupt we want to handle
System.out.println("" + this + " interrupted!");
// reset the loop counter
x = 0;
}
}
}
};
myThread.start();
}
}
答案 1 :(得分:1)
有更好的方法来结束线程。但是,如果您必须访问该线程,请使用如下的引用变量:
public void callthread(){
final Thread myThread = new Thread(new Runnable()
{
@Override
public void run()
{
final Thread _this = this;
for (int x=0; x<750&&!Thread.interrupted(); x++) {
//using this and thread sleep for repeated timed code within a thread
try {
Thread.sleep(4);
runOnUiThread(new Runnable()
{
@Override
public void run() {
//some code
if (condition) {
_this.interrupt();
}
}
});
} catch (InterruptedException e) {
}
}
}
});
答案 2 :(得分:1)
代码中的缺陷是&#34;泄漏此构造函数&#34;在线程实例化之前,您尝试调用对象的(在您的情况下)线程的方法。
要解决此问题,您可以选择类似于观察者模式的设计
答案 3 :(得分:1)
这有用吗?
作为旁注,runOnUiThread
是一种代码味道,可能导致一些相当微妙的时间错误。你用它做什么用的?要告诉你在这里想要达到的目标也很难。使用类似执行程序的东西可能会大大简化事情。
public void callthread()
{
final Thread myThread = new Thread(new Runnable()
{
@Override
public void run()
{
final Thread thread = Thread.currentThread();
for (int x = 0; x < 750 && !Thread.interrupted(); x++)
{
//using this and thread sleep for repeated timed code within a thread
try
{
Thread.sleep(4);
runOnUiThread(new Runnable()
{
@Override
public void run()
{
//some code
if (true)
{
thread.interrupt();
}
}
});
}
catch (InterruptedException e)
{
}
}
}
});
}
答案 4 :(得分:0)
部分问题是您在嵌套任务类中迷失了方向。另一部分是您尝试使用线程机制来进行逻辑控制。因此,让您的课程控制自己,并保持您的线程模型简单。
<强> ParallelTask
强>
/**
* An implementation of your inner Runnable.
*/
public class ParallelTask implements Runnable
{
protected ParallelTaskRunner m_runner = null ;
private ParallelTask() {} // Disallow default constructor.
public ParallelTask( ParallelTaskRunner runner )
{ m_runner = runner ; }
@Override
public void run()
{
// The code from that original inner class.
if( /* trigger condition */ )
m_runner.stop(this) ;
}
}
<强> ParallelTaskRunner
强>
/**
* An implementation of the outer class.
*/
public class ParallelTaskRunner implements Runnable
{
public static final int THREAD_COUNT = 750 ;
protected boolean m_bRunning = false ;
protected ParallelTask m_tskStopper = null ;
@Override
public void run()
{
if( m_bRunning ) return ; // Don't run if already running.
m_bRunning = true ; m_tskStopper = null ;
for( int i = 0 ; i < THREAD_COUNT && m_bRunning ; i++ )
{
try
{
// Insert some wait interval here if desired.
(new Thread( new ParallelTask(this) )).run() ;
}
catch( Exception x )
{
Log.w( "ParallelTaskRunner.run()",
"Caught exception.", x ) ;
}
}
}
public synchronized void stop( ParallelTask tsk )
{
m_bRunning = false ;
if( m_tskStopper == null )
m_tskStopper = tsk ;
}
public ParallelTask getStopper()
{ return m_tskStopper ; }
}
然后,在某些消费者阶层......
public void callThreads()
{
ParallelTaskRunner runner = new ParallelTaskRunner() ;
(new Thread(runner)).run() ;
}
在callThread()
方法中,您可以根据runner
中包含的数据显示报告。例如,如果您的线程使用UUID或简单整数(循环的索引?)唯一标识自己,那么您的应用程序可以使用&#34; stop&#34;来显示toast。任务的ID。如果您在ParallelTask
中执行的代码会写出有趣的数据,那么这些数据可以通过ParallelTask
中的访问者提供,然后您可以通过首先调用{{1}来调用然后对该runner.getStopper()
实例进行操作。