Java 线程和同步方法未按要求执行



我从 2 天开始连续尝试,并且已经就相关问题提出了许多 SO 问题和答案。

背景 :

  1. Runnable 类从另一个服务类接收多个调用。
  2. 可运行类必须完成已经运行和同步的方法,然后才能重新启动它

从服务调用可运行的线程:

final Singular_Processor singularProcessor = new Singular_Processor(this);
singularProcessor.start();
synchronized(singularProcessor.context)
{
while(singularProcessor.needWait)
{
wait();
}
}

实际可运行的线程类:

class Singular_Processor extends Thread
{
private static final String TAG = "Singular_Processor";
final Context context;
boolean needWait = false;
Singular_Processor(Context context)
{
this.context = context;
}
@Override
public void run()
{
try
{
doNotDisturbMe();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void doNotDisturbMe()
{
synchronized (context)
{
try
{
needWait = true;
Log.d(TAG, "RUNNING THE THREAD ID : " + Thread.currentThread().getId() + ".. n");
Thread.sleep(10000);
Log.d(TAG, "COMPLETED THE THREAD ID : " + Thread.currentThread().getId() + ".. n");
}
catch (Exception e)
{
e.printStackTrace();
Log.d(TAG, "EXCEPTION THE THREAD ID : " + Thread.currentThread().getId() + ".. n");
}
finally
{
needWait = false;
context.notifyAll();
}
}
}
}

预期输出:

2020-12-30 17:55:46.519 30184-30398/ D/Singular_Processor: RUNNING THE THREAD ID : 6053.. 
2020-12-30 17:55:50.474 30184-30455/ D/Singular_Processor: COMPLETED THE THREAD ID : 6053..
2020-12-30 17:55:56.520 30184-30398/ D/Singular_Processor: RUNNING THE THREAD ID : 6056..
2020-12-30 17:56:00.475 30184-30455/ D/Singular_Processor: COMPLETED THE THREAD ID : 6056.. 

什么是电流输出:

2020-12-30 17:55:46.519  D/Singular_Processor: RUNNING THE THREAD ID : 6053.. 
2020-12-30 17:55:50.474  D/Singular_Processor: RUNNING THE THREAD ID : 6056.. 
2020-12-30 17:55:56.520  D/Singular_Processor: COMPLETED THE THREAD ID : 6053.. 
2020-12-30 17:56:00.475  D/Singular_Processor: COMPLETED THE THREAD ID : 6056.. 

是否有任何错误:

完全不是,因为一切都是语法正确的。为什么 android 不能等待几秒钟才能在线程类上下文的完全锁定对象上完成已经运行和同步的方法,这让我很担心。我希望我在这里得到一些关于SO的想法。谢谢大家。

如果从同一服务启动Singular_Processor,则需要在所有Singular_Processor线程之间共享needWait。一种可能的解决方案是将其放在服务本身中,因为您在同一上下文上同步并使用needWait,该字段是Singular_Processor类的不同实例的字段。

Thread.sleep() 不会释放同步锁。请参阅其 javadoc:

The thread does not lose ownership of any monitors.

因此,只有一个线程可以进入同步块。

在SO上为未来的访问者发布对自己问题的回答

线程类:

class Singular_Processor extends Thread
{
private static final String TAG = "Singular_Processor";
final Context context;
Singular_Processor(Context context)
{
this.context = context;
}
@Override
public void run()
{
try
{
Log.d(TAG, "run: starting " + Thread.currentThread().getId() + ".. n");
doNotDisturbMe();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static synchronized void doNotDisturbMe()
{
try
{
Log.d(TAG, "RUNNING THE THREAD ID : " + Thread.currentThread().getId() + ".. n");
Thread.sleep(10000);
Log.d(TAG, "COMPLETED THE THREAD ID : " + Thread.currentThread().getId() + ".. n");
}
catch (Exception e)
{
e.printStackTrace();
Log.d(TAG, "EXCEPTION THE THREAD ID : " + Thread.currentThread().getId() + ".. n");
}
}
}

调用场景 :

无论您是在任何时间间隔以任何频率和从您的项目任何地方启动单个线程或多个线程......就像在我的情况下从广播接收器启动一样 -

final Singular_Processor singularProcessor = new Singular_Processor(this);
singularProcessor.start();

无论上面几行被调用多少次,以及该线程的实例被创建多少个。

  1. 因为static method永远不会为类的特定实例创建,也不会为线程实例创建。
  2. 由于我已经创建了static synchronised所有线程实例都将运行其自己的实例的方法并感到震惊,哦,我调用的方法也是静态和同步的。
  3. 个人threads are so smart and intelligent足够,我什至不需要wait任何人,也不需要费心notify任何人或notify all

预期输出 :

2020-12-30 22:31:07.856 7866-8309/MyPackage D/Singular_Processor: run: starting 7014.. 
2020-12-30 22:31:07.856 7866-8309/MyPackage D/Singular_Processor: RUNNING THE THREAD ID : 7014.. 
2020-12-30 22:31:11.285 7866-8389/MyPackage D/Singular_Processor: run: starting 7016.. 
2020-12-30 22:31:17.857 7866-8309/MyPackage D/Singular_Processor: COMPLETED THE THREAD ID : 7014.. 
2020-12-30 22:31:17.858 7866-8389/MyPackage D/Singular_Processor: RUNNING THE THREAD ID : 7016.. 
2020-12-30 22:31:27.859 7866-8389/MyPackage D/Singular_Processor: COMPLETED THE THREAD ID : 7016..