私は、0と1の単純なセマフォをセットアップしようとしています。ここで、wait()関数とSignal()関数はクリティカルセクションのスレッドのみを許可します。生産者と消費者のセマフォがメインで交互になっている実行クラスでヌルとしてセマフォを初期化する
static Semaphore lock = new Semaphore(-1); // create semaphore
Consumer consumerSemaphore = new Consumer(lock);
Producer producerSemaphore = new Producer(lock);
は、スタック内の任意の異常を起こさないために、次のように
public class Producer extends BaseThread
{
Semaphore semaphore = null;
private char block; // block to be returned
public Producer(Semaphore x)
{
this.semaphore = x;
}
public Producer()
{
// empty constructor
}
public void run()
{
try{
this.semaphore.wait(); // enter the critical section
for (int i = 0; i < 3; i++){
this.block = StackManager.stack.pick();
StackManager.stack.pick(); // return value on top
StackManager.stack.push(block++); // pushes the next char value on the stack
}
}
catch(Exception e){
allException(e);
System.exit(1);
}
finally
{
this.semaphore.Signal(); // end critical section
}
}
}
セマフォがメインで宣言されています。 (Consumerクラスは本質的にProducerと同じように書かれていますが、代わりにpop()を実行するので、Consumerクラスは省略しました)。
ここでの問題は、コードを実行しているときにConsumerクラスとProducerクラスの両方でNullPointerExceptionエラーが発生し続けていることです。答えが見つからないようです。私はここで何が欠けていますか?
EDIT: コードはStackManager.stackの先頭の次のchar値をプッシュする必要がありますが、Consumerという別のクラスもpop()操作を行っているので、同期を実行する必要があります。
class Semaphore {
private int value;
public Semaphore(int value) {
this.value = value;
}
public Semaphore() {
this(0);
}
public synchronized void Wait() {
while (this.value >= 0) { //changed to greater or equals since we're doing the opposite with natural numbers
try {
wait();
}
catch(InterruptedException e) {
System.out.println ("Semaphore::Wait() - caught InterruptedException: " + e.getMessage());
e.printStackTrace();
}
}
this.value++; // the semaphore value gets incremented since it needs to go to zero from -1 or lower
}
public synchronized void Signal() {
--this.value; // signal decrements the value since it brings the lock back to -1 for the next wait operation
notify();
}
public synchronized void P() {
this.Wait();
}
public synchronized void V() {
this.Signal();
}
}
お知らせセマフォは、()-1として、当然の複雑さのために、私たちが必要とするので、メインで初期化されています。私は他の何かが、私が作成したこのクラスでセマフォを使用することはできませんSemaphoreクラスを作成します。-1は次のスレッドの準備ができていることを意味し、0はスレッドがクリティカルセクションにあることを意味します。これは、私がインクリメントとシグナルデクリメントを書いたwait()メソッドを意味します。
編集2:追加されましたConsumerクラス
public class Consumer extends BaseThread {
Semaphore semaphore = null;
private char copy; // A copy of a block returned by pop()
public Consumer(Semaphore x) {
this.semaphore = x;
}
public Consumer() {
// empty constructor
}
public void run() {
try {
this.semaphore.wait(); // enter the critical section
System.out.println("Consumer thread [TID=" + this.iTID + "] starts executing.");
for (int i = 0; i < StackManager.iThreadSteps; i++) {
this.copy = StackManager.stack.pop(); // pop the top of the stack
System.out.println("Consumer thread [TID=" + this.iTID + "] pops character =" + this.copy);
}
System.out.println("Consumer thread [TID=" + this.iTID + "] terminates.");
} catch (Exception e) {
allException(e);
System.exit(1);
} finally {
this.semaphore.Signal(); // end the critical section
}
}
}
EDIT 3:
class StackManager {
// The Stack
public static CharStack stack = new CharStack();
private static final int NUM_ACQREL = 4; // Number of Producer/Consumer threads
private static final int NUM_PROBERS = 1; // Number of threads dumping stack
public static int iThreadSteps = 3; // Number of steps they take
// Semaphore declarations. Insert your code in the following:
static Semaphore lock = new Semaphore(-1); // create semaphore
Consumer consumerSemaphore = new Consumer(lock);
Producer producerSemaphore = new Producer(lock);
CharStackProber stackProberSemaphore = new CharStackProber(lock);
// The main
public static void main(String[] argv)
{
// Some initial stats...
try
{
System.out.println("Main thread starts executing.");
System.out.println("Initial value of top = " + stack.getTop() + ".");
System.out.println("Initial value of stack top = " + stack.pick() + ".");
System.out.println("Main thread will now fork several threads.");
}
catch(CharStackEmptyException e)
{
System.out.println("Caught exception: StackCharEmptyException");
System.out.println("Message : " + e.getMessage());
System.out.println("Stack Trace : ");
e.printStackTrace();
}
/*
* The birth of threads
*/
Consumer ab1 = new Consumer();
Consumer ab2 = new Consumer();
System.out.println ("Two Consumer threads have been created.");
Producer rb1 = new Producer();
Producer rb2 = new Producer();
System.out.println ("Two Producer threads have been created.");
CharStackProber csp = new CharStackProber();
System.out.println ("One CharStackProber thread has been created.");
/*
* start executing
*/
ab1.start();
rb1.start();
ab2.start();
rb2.start();
csp.start();
/*
* Wait by here for all forked threads to die
*/
try
{
ab1.join();
ab2.join();
rb1.join();
rb2.join();
csp.join();
// Some final stats after all the child threads terminated...
System.out.println("System terminates normally.");
System.out.println("Final value of top = " + stack.getTop() + ".");
System.out.println("Final value of stack top = " + stack.pick() + ".");
System.out.println("Final value of stack top-1 = " + stack.getAt(stack.getTop() - 1) + ".");
System.out.println("Stack access count = " + stack.getAccessCounter());
}
catch(InterruptedException e)
{
System.out.println("Caught InterruptedException: " + e.getMessage());
System.exit(1);
}
catch(Exception e)
{
System.out.println("Caught exception: " + e.getClass().getName());
System.out.println("Message : " + e.getMessage());
System.out.println("Stack Trace : ");
e.printStackTrace();
}
}
}
スタックトレースは以下の通りである:これは短いポスト維持のために
Main thread starts executing.
Initial value of top = 3.
Initial value of stack top = d.
Main thread will now fork several threads.
Two Consumer threads have been created.
Two Producer threads have been created.
One CharStackProber thread has been created.
Caught exception : java.lang.NullPointerException
Caught exception : java.lang.NullPointerException
Message : null
Caught exception : java.lang.NullPointerException
Caught exception : java.lang.NullPointerException
Caught exception : java.lang.NullPointerException
Message : null
Stack Trace :
Stack Trace :
Message : null
Stack Trace :
Message : null
Stack Trace :
Message : null
Stack Trace :
java.lang.NullPointerException
at Producer.run(Producer.java:18)
java.lang.NullPointerException
at CharStackProber.run(CharStackProber.java:18)
java.lang.NullPointerException
at Consumer.run(Consumer.java:19)
java.lang.NullPointerException
at Consumer.run(Consumer.java:19)
、I CharStackProberクラスはProducerのコピーであるため、run()メソッドはまったく同じですが内部はF forループStackManager.stack
NPEを取得すると、スタックトレースが取得され、質問に追加し、どのラインをトリガーするかを表示します。 – alfasin
多くの質問があります...あなたのコードは何をしていますか? 'セマフォ'クラスとは何ですか? 「消費者」のコードはどこですか?シンプルなロックの代わりにセマフォを使うのはなぜですか? 'wait()'を呼び出すのは何ですか? 'Signal()'とは何ですか?どこでNPEを取得していますか?スタックトレースはどこですか?実際の調査やデバッグはまだ完了していますか? – shmosel
@alfasin「this.semaphore.wait()」のエラーが表示されます – PatrickVNB