2017-04-01 44 views
0

我是Java多线程编程的新手。我有一个用例,我有一个名为Diner的可运行类,并基于程序中不同变量的状态,我想要并行执行Diner类的不同方法。 要做到这一点的一种方法是将一个run()方法包含多个if条件,这些条件对应于您要执行的不同代码块,如下所示。具有多种方法的Java类可以在线程中执行

public class Diner implements Runnable { 
     Order order; 
     int arrivalTime; 



     public void run() { 
      if(!isSeated){ 
       //do something to get a seat 
      } 
      if(!notEatenYet){ 
       //place order 
      } 
      if(!orderHasArrived){ 
       //start eating 
      } 
      if(finishedEating){ 
       //pay bill and leave 
      } 
     } 
    } 

但是,有没有更好的方法来做到这一点?类似于可以并行化的单个方法(run()?),可以使用不同的方法进行并行化(过载run()?)。

我相信我可以使用Akka Actor来完成这样的事情,但我正在寻找一个本地解决方案。

+0

你refered这一点,你只是用'ExectutorService引用的文章http://crunchify.com/how-to-run-multiple-threads-concurrently-in-java-executorservice-approach/ –

+0

@RajithPemabandu '启动并管理多个线程,而不是为每个线程创建一个单独的'Thread'对象。所有创建的线程只有一个任务需要并行执行,即Ping主机。这不是我的问题所指的。 –

+0

你真的想要并行运行类的方法吗?我几乎无法想象一个同时坐下,吃饭和付帐的小餐馆:这种行为是严格顺序的。 –

回答

2

如果您是多线程新手,请考虑逐步放宽。从单个工作线程开始,并将所有用餐者的任务发布到这一个线程。这提供了一些并发性 - 向线程提交任务不会阻塞 - 但是消除了多个线程同时访问同一个Diner的许多复杂性(同步,死锁风险,竞争条件风险等)

这里是一个使用单线程调度执行程序的示例。它调度一些事件发生在2,4和6秒,但调用线程不会阻止等待每个事件(尽管我在倒数锁存器末尾添加了一个仿真块,因此我们可以干净地关闭执行程序)

public class Diner { 

    public void findSeat() { 
     System.out.println("findSeat"); 
    } 
    public void placeOrder() { 
     System.out.println("placeOrder"); 
    } 

    public static void main(String[] args) throws InterruptedException { 
     final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); 
     final CountDownLatch done = new CountDownLatch(1); 

     final Diner diner = new Diner(); 

     exec.schedule(new Runnable() { 
      public void run() { 
       diner.findSeat(); 
      } 
     }, 2, TimeUnit.SECONDS); 

     exec.schedule(new Runnable() { 
      public void run() { 
       diner.placeOrder(); 
      } 
     }, 4, TimeUnit.SECONDS); 


     exec.schedule(new Runnable() { 
      public void run() { 
       done.countDown(); 
      } 
     }, 6, TimeUnit.SECONDS); 

     done.await(); 
     exec.shutdown(); 
     System.out.println("done"); 
    } 
} 

此外,您的Diner无需实现Runnable。只需为每个任务创建临时 可运行的应用程序。

当您需要额外的并发时,请添加第二个,第三个执行程序服务。如果您的 具有“无状态”任务 - 例如数据库查询 - 您可以添加一个新的带多个线程的执行程序服务以获得更好的并行性。只需确保 当您更新您的小餐馆时,您的db线程通过将任务安排到Diner 执行程序,而不是直接修改diner。

这会给你一种阿卡式的风格,但只使用本地Java实用程序。

1
public class SOCLass { 

    public void method1(){ 
     System.out.println("method1"); 
    } 

    public void method2(){ 
     System.out.println("method1"); 
    } 

    public static void main(String[] args){ 
     SOCLass clazz = new SOCLass(); 

     Runnable task1 =() -> { clazz.method1();};  
     Thread t1 = new Thread(task1); 
     t1.start(); 

     Runnable task2 =() -> { clazz.method2();};  
     Thread t2 = new Thread(task1); 
     t2.start(); 

     try { 
      t1.join(); 
      t2.join(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

编辑

我觉得你的情况下,这个方法会更好地工作。评估布尔值后,您可以在启动任务方法中启动线程。只是一个晚餐实例

就守在原地线程,你可以控制他们

0

在我看来,你的情况下,简单的继承可以是一个很好的选择。

你可以有几个子类继承Diner

所以会有一个晚餐抽象类和几个子类,

public abstract class Diner implements Runable{ 
    public Order order; 
    public int arrivalTime; 
} 

public class NotSeatedDiner extends Diner { 
    public void run() { 
     // do something to find a seat 
    } 
} 

//一些其他子类

在主功能,你可以有

List diners = new ArrayList<Diner>(); 

//maybe some factory producing different diners 

diners.add(fac.getDiner("not seated")); 

for(Diner diner : diners){ 
    diner.run(); 
} 
相关问题