2017-03-18 34 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; 
    } 
} 

第二类是实现Runnable和Observer的EdgeGenerator。

该observable是KochFractal类(这里不包括)。 更新方法在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关键字。这是我的理解,这使得实例方法一次只能访问一个线程,并保持其他线程。

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来代替。您最初创建一项服务,然后将新任务推送到该服务中。加上期货应该允许更优雅的解决方案。正如Hovercraft所建议的,你也可以让UI更新更频繁。

+1

或GUI线程递增更新绘图,每次工作线程已更新图形数据并已通知GUI。 (1+) –

+0

或者那个。这里有许多有趣的选项。和:晚上(或早上)鳗鱼先生。或者我可以叫你气垫船? :-) – GhostCat

+0

先生,鳗鱼先生,会做得很好。 LOL –