Java多线程编程中首先对任务进行排队。调用执行器服务点新的固定线程池并提供大小。此大小表示同时任务的最大数量。例如,如果将一千个事物添加到队列中,但池大小为 50,那么任何时候都只有 50 个在运行。只有当前 50 个中的一个完成执行时,才会占用第 51 个执行。像 100 这样的数字作为池大小不会使系统过载。
ExecutorService taskList = Executors.newFixedThreadPool( poolSize );
然后,用户必须将一些可运行类型的任务放入任务队列。Runnable 只是一个单一的接口,它有一个名为 run 的方法。系统在适当的时候通过启动一个单独的线程在任务之间来回切换时调用run方法。
taskList.execute( someRunnable )
Execute 方法有点用词不当,因为当一个任务被添加到上面创建的队列中的任务中时,执行器 dot new 固定线程池,它不一定立即开始执行它。当同时执行的其中一个(池大小)完成执行时,它开始执行。
首先要做的是创建一个单独的类,并且是一个完全独立的类,它实现了可运行接口。
公共类 MyRunnable实现 Runnable {
公共无效运行(){...}
}
其次制作主类的一些实例并将它们传递给执行。让我们应用第一种方法来制作只计数的线程。因此,每个线程都会打印线程名称、任务号和计数器值。
在此之后使用 pause 方法坐下来等待,以便系统来回切换。打印语句将因此被交错。
将构造函数参数传递给 Runnable 的构造函数,以便不同的实例计算不同的次数。
调用关闭方法意味着关闭正在监视的线程以查看是否添加了任何新任务。
实际实施
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author evivehealth on 08/02/19.
*/
// Java program depicting
// concurrent programming in action.
// Runnable Class that defines the logic
// of run method of runnable interface
public class Counter implements Runnable
{
private final MainApp mainApp;
private final int loopLimit;
private final String task;
// Constructor to get a reference to the main class
public Counter
(MainApp mainApp, int loopLimit, String task)
{
this.mainApp = mainApp;
this.loopLimit = loopLimit;
this.task = task;
}
// Prints the thread name, task number and
// the value of counter
// Calls pause method to allow multithreading to occur
@Override
public void run()
{
for (int i = 0; i < loopLimit; i++)
{
System.out.println("Thread: " +
Thread.currentThread().getName() + " Counter: "
+ (i + 1) + " Task: " + task);
mainApp.pause(Math.random());
}
}
}
class MainApp
{
// Starts the threads. Pool size 2 means at any time
// there can only be two simultaneous threads
public void startThread()
{
ExecutorService taskList =
Executors.newFixedThreadPool(2);
for (int i = 0; i < 5; i++)
{
// Makes tasks available for execution.
// At the appropriate time, calls run
// method of runnable interface
taskList.execute(new Counter(this, i + 1,
"task " + (i + 1)));
}
// Shuts the thread that's watching to see if
// you have added new tasks.
taskList.shutdown();
}
// Pauses execution for a moment
// so that system switches back and forth
public void pause(double seconds)
{
try
{
Thread.sleep(Math.round(1000.0 * seconds));
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
// Driver method
public static void main(String[] args)
{
new MainApp().startThread();
}
}
输出:
线程:pool-1-thread-1 计数器:1 任务:任务 1
线程:pool-1-thread-2 计数器:1 任务:任务 2
线程:pool-1-thread-2 计数器:2 任务:任务 2
线程:pool-1-thread-1 计数器:1 任务:任务 3
线程:pool-1-thread-2 计数器:1 任务:任务 4
线程:pool-1-thread-1 计数器:2 任务:任务 3
线程:pool-1-thread-1 计数器:3 任务:任务 3
线程:pool-1-thread-1 计数器:1 任务:任务 5
线程:pool-1-thread-2 计数器:2 任务:任务 4
线程:pool-1-thread-2 计数器:3 任务:任务 4
线程:pool-1-thread-1 计数器:2 任务:任务 5
线程:pool-1-thread-2 计数器:4 任务:任务 4
线程:pool-1-thread-1 计数器:3 任务:任务 5
线程:pool-1-thread-1 计数器:4 任务:任务 5
线程:pool-1-thread-1 计数器:5 任务:任务 5
优点:
松散耦合:由于可以重用单独的类,因此它促进了松散耦合。
构造函数:参数可以传递给不同情况的构造函数。例如,描述线程的不同循环限制。
竞争条件:如果数据已共享,则不太可能使用单独的类作为方法,如果它没有共享数据,则无需担心竞争条件。
缺点:
回调主应用有点不方便。必须通过Java构造函数传递引用,即使可以访问引用,也只能调用主应用程序中的公共方法(给定示例中的暂停方法)。
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习