2017-03-18 11 views
1

スレッドを使用してJavaプログラムを作成していますが、いくつかの問題が発生し続けています。Javaスレッドが中断していない

学校向けのプロジェクトであり、コッホのフラクタルをいくつか作成する必要があります。

最初のクラスはマネージャです。 EdgeGeneratorを使用してKochフラクタルのエッジを生成するスレッドが作成されます。

import java.util.logging.Level; 
import java.util.logging.Logger; 
import uckochfractalfx.UCKochFractalFX; 

public class KochManager { 
    private final UCKochFractalFX application; 
    private final IEdgeCollection edges; 

    private int level; 
    private int count; 

    public KochManager(UCKochFractalFX application) { 
     this.application = application; 
     this.edges = new EdgeArrayList(); 
    } 

    public synchronized void changeLevel(int nxt){ 
     this.level = nxt; 
     this.count = 0; 
     this.edges.clear(); 

     EdgeGenerator left, right, bottom; 
     left = new EdgeGenerator(this, EdgeLocation.LEFT); 
     right = new EdgeGenerator(this, EdgeLocation.RIGHT); 
     bottom = new EdgeGenerator(this, EdgeLocation.BOTTOM); 

     Thread tLeft, tRight, tBottom; 
     tLeft = new Thread(left); 
     tRight = new Thread(right); 
     tBottom = new Thread(bottom);    

     tLeft.start(); 
     tRight.start(); 
     tBottom.start(); 

     try { 
      tLeft.join(500); 
      tRight.join(500); 
      tBottom.join(500); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(KochManager.class.getName()).log(Level.SEVERE, null, ex); 
     } 


     application.requestDrawEdges(); 
    } 

    public void addEdge(Edge edge){ 
     this.edges.add(edge); 
    } 

    public synchronized void increaseCount(){ 
     count ++; 
    } 

    public int getLevel() { 
     return level; 
    } 
} 

2番目のクラスは、RunnableとObserverを実装するEdgeGeneratorです。

観測可能なのはKochFractalクラス(ここには含まれていません)です。 updateメソッドは、KochFractalのgenerate__Edge()メソッドで呼び出されます。 これはすべて正常に動作し、スレッドとスレッドを使用せずにテストされます。

import java.util.Observable; 
import java.util.Observer; 

public class EdgeGenerator implements Runnable, Observer { 
    private final KochManager kochManager; 
    private final EdgeLocation edgeLocation; 
    private final KochFractal koch; 

    public EdgeGenerator(KochManager kochManager, EdgeLocation edgeLocation) { 
     this.kochManager = kochManager; 
     this.edgeLocation = edgeLocation; 
     this.koch = new KochFractal();   
     this.koch.addObserver(this); 
    } 


    @Override 
    public void run() { 
     koch.setLevel(kochManager.getLevel()); 
     switch (this.edgeLocation) { 
      case LEFT: 
       this.koch.generateLeftEdge(); 
       break; 
      case RIGHT: 
       this.koch.generateRightEdge(); 
       break; 
      case BOTTOM: 
       this.koch.generateBottomEdge(); 
       break; 
     } 
     Thread.currentThread().interrupt(); 
    } 

    @Override 
    public void update(Observable o, Object o1) { 
     this.kochManager.addEdge((Edge)o1); 
     this.kochManager.increaseCount(); 
    }  
} 

最後のクラスは、ArrayListを使用するコレクションクラスです。 追加と削除時にsynchronizedキーワードを使用しました。これにより、インスタンスメソッドは一度に1つのスレッドのみにアクセス可能になり、他のスレッドを保留にすることができます。

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 

public class EdgeArrayList implements IEdgeCollection{  
    private final List<Edge> edges; 

    public EdgeArrayList() { 
     this.edges = new ArrayList<>(); 
    } 

    @Override 
    public synchronized void add(Edge e) {   
     edges.add(e); 
    } 

    @Override 
    public synchronized void remove(Edge e) { 
     edges.remove(e); 
    } 

    @Override 
    public void clear() { 
     edges.clear(); 
    } 

    @Override 
    public List<Edge> getAll() { 
     return Collections.unmodifiableList(edges); 
    }  
} 

ここでは何が起こっていますか?

  • ここに実装されているようにプログラムを実行すると、フラクタル要素のうちのほんの一部がGUIに表示されます。 しかし、いったん多くの辺を計算しなければならない場合、それらの辺はguiに表示されます。 デバッガを使用すると、すべてのエッジが計算されていることがわかりますが、すべてのエッジが計算される前にapplication.requestDrawEdges();が呼び出されました。
  • join()メソッドで遅延なしでプログラムを実行すると、GUIは表示されずに実行されます。

は、私の知る限りではThread.currentThread().interrupt();は、現在のスレッドを停止し、join()メソッドを呼び出し、それは起きていないはずです。

誰かが私を正しい方向に向けることを願っています。

+0

@GhostCat私の悪い、私はちょうどそれを夜に呼び出す前に、この質問を投稿しました。私はすぐにこれに取り組み始め、あなたに知らせます。 –

+0

受け入れてくれてありがとう、私は助けになってうれしいです。 – GhostCat

答えて

2

あなたの参加の理解は間違っています。

あなたのメインスレッドは、各地下に参加するためにそれらの500ミリ秒を単に待つでしょう...しかし、それが起こらなければ、コードの実行は単に続行されます。つまり、約1.5秒後に描画が開始されます。

低レベルのプリミティブ結合を使用する代わりに、各サブスレッドではなく、「完了しました」とアクティブにアナウンスすることができます。そしてあなたのメインスレッドは、すべてのサブスレッドがそれを行うのを待つだけです。

それを超えて:スレッドオブジェクトはかなり "高価"です。あなたは本当に各反復の後にそれらを放棄すべきではありません。代わりに、代わりにExecutorServiceを使用します。最初に1つのサービスを作成し、新しいタスクをそのサービスにプッシュするだけです。 Futuresと一緒に、より洗練されたソリューションを可能にする必要があります。また、ホバークラフトが示唆するように、あなたはUIがより頻繁に更新されるようにすることもできます。

+1

またはGUIスレッドは、ワーカースレッドがグラフデータを更新し、GUIに通知するたびに、図面を段階的に更新します。 (1 +) –

+0

またはそれ。多くの興味深いオプションがここにあります。そして:良い夜(または朝)Eelさん。ホバークラフトと呼んでもいいですか? :-) – GhostCat

+0

Eelさん、よろしくお願いします。 LOL –

関連する問題