在Java中,如何在每个线程中运行不同的方法?

发布于 2024-11-09 10:20:39 字数 1198 浏览 0 评论 0原文

更新:我混合使用了 extraneon 和 Jarrod Roberson 的答案。

我目前有四种想要同时运行的方法。它们是对数据库的四个查询。

我需要实现四个类,每个类都有一个 run() 和所需的查询,或者还有其他方法可以做到这一点?

编辑:这些方法将更新程序中的统计信息,并在名为StatisticsDB的类中实现(下面的这些方法来自Facade,因为这些方法比这个更大)。我有一个类将更新在后台线程中运行的统计信息。我想要这样的东西,并且每个线程可以有一个连接。

public void updateStatistics(){
    //these methods running at same time
    pages = getQuantityVisitedPages();
    links = getQuantityFoundLinks();
    blinks = getQuantityBrokenLinks();
    flinks = getQuantityFilteredLinks();
}

public String getQuantityVisitedPages(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityVisitedPages(conn);
}

public String getQuantityFoundLinks(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityFoundLinks(conn);
}

public String getQuantityBrokenLinks(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityFilteredLinks(conn);
}

public String getQuantityFilteredLinks(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityFilteredLinks(conn);
}

UPDATE: I have used a mix of the answers by extraneon and Jarrod Roberson.

I have currently four methods that I want to run at same time. They are four queries to database.

I need to implement four classes, each one with a run() with the desired query or there another way to do this?

EDIT: These methods will update statistics in the program and are implemented in a class called StatisticsDB (these methods below are from the Facade because the methods are greater than this). I have a class that will update the statistics that run in a thread in backgroud. I want something like this and can be one connection per thread.

public void updateStatistics(){
    //these methods running at same time
    pages = getQuantityVisitedPages();
    links = getQuantityFoundLinks();
    blinks = getQuantityBrokenLinks();
    flinks = getQuantityFilteredLinks();
}

public String getQuantityVisitedPages(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityVisitedPages(conn);
}

public String getQuantityFoundLinks(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityFoundLinks(conn);
}

public String getQuantityBrokenLinks(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityFilteredLinks(conn);
}

public String getQuantityFilteredLinks(Connection conn) {
    statisticsDB = new StatisticsDB();
    return statisticsDB.getQuantityFilteredLinks(conn);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

長街聽風 2024-11-16 10:20:39

Future 与 Callable 和执行者服务。

// Don't use the connection on all queries at the same time
// unless that's allowed.
Future<String> f1 = executor.submit(new Callable<String>() {
     public String call() {
         return getQuantityVisitedPages( createConnection() );
     }});
Future<String> f2 = executor.submit(new Callable<String>() {
     public String call() {
         return getQuantityFoundLinks( createConnection() );
     }});


 try {
   // wait until f1 is finished and get the result
   // in the mean time all queries are running
   String qvp = f1.get(); 
   String qfl = f2.get();
 } catch (ExecutionException ex) { cleanup(); return; }

 // do something with found values

编辑

需要明确的是 - 如果单个查询失败,您现在将一无所有。如果您可以接受缺少一个结果的情况,您只需将 try - catch 包裹在每个 get() 周围即可。

get() 是阻塞的(尽管可以选择超时。因此,如果同时结果已确定,f2.get() 将立即返回,否则它将等待,直到 f2 也准备好。

如果您想更新查询完成后立即更新 GUI 部分,或者使用 SwingWorker 代替 future。

请务必小心类成员变量 - 对共享状态的并发访问可能很棘手。如果你连接。使用连接池,从池中为每个调用提供自己的连接。

,当发生异常时,只需获取 Cause() 并确定应该执行的操作。

get() 语义表明 我认为 new Executors.newFixedThreadPool(4) 就可以了,或者如果您认为会有更多查询,请使用 newCachedThreadPool。查询对于您的 CPU 来说并不是那么密集(尽管它们是针对数据库服务器的),因此一些额外的线程并不是真正的问题,因为它们无论如何都在等待数据库结果。

Use a Future with a Callable and ExecutorService.

// Don't use the connection on all queries at the same time
// unless that's allowed.
Future<String> f1 = executor.submit(new Callable<String>() {
     public String call() {
         return getQuantityVisitedPages( createConnection() );
     }});
Future<String> f2 = executor.submit(new Callable<String>() {
     public String call() {
         return getQuantityFoundLinks( createConnection() );
     }});


 try {
   // wait until f1 is finished and get the result
   // in the mean time all queries are running
   String qvp = f1.get(); 
   String qfl = f2.get();
 } catch (ExecutionException ex) { cleanup(); return; }

 // do something with found values

EDIT

Just to be clear - if a single query fails you now have nothing. If you can live with one result missing you just wrap the try - catch around every single get().

A get() is blocking (though optionally takes a time-out. So f2.get() will return immediately if in the mean time the results have been determine, otherwise it will wait untill f2 is also ready.

If you want to update a GUI immediately when a query is finished make updating the gui part of the callable, or use a SwingWorker in stead of a future.

Do be carefull with class member variables - concurrent access to shared state can be tricky. That's why I warned about the connection. If you use aa connection pool, give every call its own connection from the pool.

get() semantics state that when an exception occurs it's wrapped in the ExecutionException. Just get the cause() and determine what should be done.

As for an appropriate executor, I think a new Executors.newFixedThreadPool(4) will serve just fine, or use a newCachedThreadPool if you think more queries will follow. Queries aren't that intensive for your CPU (they are for the database server though) so a few extra threads are not really a problem as they are waiting for the database results anyway.

爱*していゐ 2024-11-16 10:20:39

您想从 java.util.concurrent 包中了解有关 FuturesCallable 的内容。

以下是您的代码应该是什么样子的基本概念:

import java.sql.ResultSet;
import java.util.concurrent.*;

public class Main
{
    public static void main(final String[] args)
    {
        final ExecutorService es = Executors.newFixedThreadPool(5);
        final Future<ResultSet> rs1 = es.submit(new Query01());
        final Future<ResultSet> rs2 = es.submit(new Query02());
        final Future<ResultSet> rs3 = es.submit(new Query03());
        final Future<ResultSet> rs4 = es.submit(new Query04());

        // then you can test for completion with methods on
        // rs1, rs2, rs3, rs4 and get the ResultSet with rs1.get();

        while ( !f1.isDone() && !f2.isDone() && !f3.isDone() && !f4.isDone() )
        {
            // handle results that are complete
        }
    }

    public static class Query01 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }
     public static class Query02 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }
        public static class Query03 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }
        public static class Query04 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }

}

What you want to learn about Futures and Callable from the java.util.concurrent package.

Here is a basic idea of what your code should look like:

import java.sql.ResultSet;
import java.util.concurrent.*;

public class Main
{
    public static void main(final String[] args)
    {
        final ExecutorService es = Executors.newFixedThreadPool(5);
        final Future<ResultSet> rs1 = es.submit(new Query01());
        final Future<ResultSet> rs2 = es.submit(new Query02());
        final Future<ResultSet> rs3 = es.submit(new Query03());
        final Future<ResultSet> rs4 = es.submit(new Query04());

        // then you can test for completion with methods on
        // rs1, rs2, rs3, rs4 and get the ResultSet with rs1.get();

        while ( !f1.isDone() && !f2.isDone() && !f3.isDone() && !f4.isDone() )
        {
            // handle results that are complete
        }
    }

    public static class Query01 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }
     public static class Query02 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }
        public static class Query03 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }
        public static class Query04 implements Callable<ResultSet>
    {
        public ResultSet call() throws Exception 
        {
            // Do work here and return ResultSet
            return null;
        }
    }

}
流绪微梦 2024-11-16 10:20:39

更新:没有注意到它与java有关,

但我将在这里保留C#版本:

Task<string> task1 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityVisitedPages(conn);
  }
Task<string> task2 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityFoundLinks(conn);
  }
Task<string> task3 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityBrokenLinks(conn);
  }
Task<string> task4 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityFilteredLinks(conn);
  }
Task.WaitAll(task1, task2, task3, task4);
Console.WriteLine(task1.Result);
Console.WriteLine(task2.Result);
Console.WriteLine(task3.Result);
Console.WriteLine(task4.Result);

UPDATE: haven't notice that it is related to java

however I will leave here C# version:

Task<string> task1 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityVisitedPages(conn);
  }
Task<string> task2 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityFoundLinks(conn);
  }
Task<string> task3 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityBrokenLinks(conn);
  }
Task<string> task4 = Task.Factory.StartNew<string>(() => 
  {
    return getQuantityFilteredLinks(conn);
  }
Task.WaitAll(task1, task2, task3, task4);
Console.WriteLine(task1.Result);
Console.WriteLine(task2.Result);
Console.WriteLine(task3.Result);
Console.WriteLine(task4.Result);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文