以一个案例功能来初步认识一下java多线程编程。
Java多线程编程安全关键字volatile、synchronized,及api Executors|ExecutorService的基本用法
一.首先基础准备
volatile修饰符的作用:被volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,多个不同的线程总是看到某个成员变量的同一个值。
synchronized修饰符的作用:被synchronized 关键字锁定的对象(方法、代码块、成员变量/对象)同一时间只能被一个线程访问,这样确保了在多线程环境的线程安全。
java 多线程相关api:Executors、ExecutorService、Thread、Runnable等相关api,此处不一一列出,可自行查阅Java™ Platform Standard Ed. 8文档。
1).Executors:java.util.concurrent.Executors
Class Executors | ||
All Methods | ||
Modifier and Type | Method and Description | |
static Callable<Object> | callable(PrivilegedAction<?> action) | |
Returns a Callable object that, when called, runs the given privileged action and returns its result. | 返回一个可调用对象,该对象在被调用时运行给定的特权操作并返回其结果。 | |
static Callable<Object> | callable (PrivilegedExceptionAction<?> action) |
|
Returns a Callable object that, when called, runs the given privileged exception action and returns its result. | 返回一个可调用对象,该对象在被调用时运行给定的特权异常操作并返回其结果。 | |
static Callable<Object> | callable(Runnable task) | |
Returns a Callable object that, when called, runs the given task and returns null. | 返回一个可调用对象,该对象在被调用时运行给定的任务并返回null。 | |
static <T> Callable<T> | callable(Runnable task, T result) | |
Returns a Callable object that, when called, runs the given task and returns the given result. | 返回一个可调用的对象,该对象在被调用时运行给定的任务并返回给定的结果。 | |
static ThreadFactory | defaultThreadFactory() | |
Returns a default thread factory used to create new threads. | 返回用于创建新线程的默认线程工厂。 | |
static ExecutorService | newCachedThreadPool() | |
Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. | 创建一个线程池,该线程池根据需要创建新线程,但在以前构造的线程可用时将重用它们。 | |
static ExecutorService | newCachedThreadPool (ThreadFactory threadFactory) |
|
Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available, and uses the provided ThreadFactory to create new threads when needed. | 创建一个线程池,该线程池根据需要创建新线程,但在以前构造的线程可用时将重用这些线程,并在需要时使用提供的ThreadFactory创建新线程。 | |
static ExecutorService | newFixedThreadPool (int nThreads) |
|
Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. | 创建一个线程池,该线程池重用在共享无边界队列上运行的固定数量的线程。 | |
static ExecutorService | newFixedThreadPool (int nThreads, ThreadFactory threadFactory) |
|
Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue, using the provided ThreadFactory to create new threads when needed. | 创建一个线程池,该线程池重用在共享无边界队列中运行的固定数量的线程,在需要时使用提供的ThreadFactory创建新线程。 | |
static ScheduledExecutorService |
newScheduledThreadPool(int corePoolSize) | |
Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically. | 创建一个线程池,该线程池可以安排命令在给定延迟后运行,或定期执行。 | |
static ScheduledExecutorService |
newScheduledThreadPool (int corePoolSize, ThreadFactory threadFactory) |
|
Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically. | 创建一个线程池,该线程池可以安排命令在给定延迟后运行,或定期执行。 | |
static ExecutorService | newSingleThreadExecutor() | |
Creates an Executor that uses a single worker thread operating off an unbounded queue. | 创建一个执行器,该执行器使用一个工作线程在无边界队列中进行操作。 | |
static ExecutorService | newSingleThreadExecutor (ThreadFactory threadFactory) |
|
Creates an Executor that uses a single worker thread operating off an unbounded queue, and uses the provided ThreadFactory to create a new thread when needed. | 创建一个执行器,该执行器使用单个工作线程在无界队列外运行,并在需要时使用提供的ThreadFactory创建新线程。 | |
static ScheduledExecutorService |
newSingleThreadScheduledExecutor() | |
Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically. | 创建一个单线程执行器,该执行器可以安排命令在给定延迟后运行,或定期执行。 | |
static ScheduledExecutorService |
newSingleThreadScheduledExecutor (ThreadFactory threadFactory) |
|
Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically. | 创建一个单线程执行器,该执行器可以安排命令在给定延迟后运行,或定期执行。 | |
static ExecutorService | newWorkStealingPool() | |
Creates a work-stealing thread pool using all available processors as its target parallelism level. | 使用所有可用的处理器作为其目标并行级别来创建工作线程池。 | |
static ExecutorService | newWorkStealingPool (int parallelism) |
|
Creates a thread pool that maintains enough threads to support the given parallelism level, and may use multiple queues to reduce contention. | 创建一个线程池,该线程池维护足够的线程以支持给定的并行级别,并且可以使用多个队列来减少争用。 | |
static <T> Callable<T> | privilegedCallable (Callable<T> callable) |
|
Returns a Callable object that will, when called, execute the given callable under the current access control context. | 返回一个可调用对象,该对象在被调用时将在当前访问控制上下文下执行给定的可调用对象。 | |
static <T> Callable<T> | privilegedCallableUsingCurrentClassLoader (Callable<T> callable) |
|
Returns a Callable object that will, when called, execute the given callable under the current access control context, with the current context class loader as the context class loader. | 返回一个可调用对象,该对象在被调用时,将在当前访问控制上下文下执行给定的可调用对象,并将当前上下文类装入器作为上下文类装入器。 | |
static ThreadFactory | privilegedThreadFactory() | |
Returns a thread factory used to create new threads that have the same permissions as the current thread. | 返回用于创建与当前线程具有相同权限的新线程的线程工厂。 | |
static ExecutorService | unconfigurableExecutorService (ExecutorService executor) |
|
Returns an object that delegates all defined ExecutorService methods to the given executor, but not any other methods that might otherwise be accessible using casts. | 返回一个对象,该对象将所有已定义的ExecutorService方法委托给给定的executor,但不委托任何其他可以使用强制转换访问的方法。 | |
static ScheduledExecutorService |
unconfigurableScheduledExecutorService (ScheduledExecutorService executor) |
|
Returns an object that delegates all defined ScheduledExecutorService methods to the given executor, but not any other methods that might otherwise be accessible using casts. | 返回一个对象,该对象将所有已定义的ScheduledExecutorService方法委托给给定的执行器,但不委托任何其他可能使用强制转换访问的方法。 |
2).ExecutorService:java.util.concurrent.ExecutorService
Interface ExecutorService | ||
All Methods | ||
Modifier and Type | Method and Description | |
boolean | awaitTermination(long timeout, TimeUnit unit) | |
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first. | 在关闭请求、超时或当前线程中断(以先发生的为准)之后,阻塞直到所有任务都已完成执行。 | |
<T> List<Future<T>> | invokeAll(Collection<? extends Callable<T>> tasks) | |
Executes the given tasks, returning a list of Futures holding their status and results when all complete. | 执行给定的任务,当所有任务都完成时,返回一个保存其状态和结果的未来列表。 | |
<T> List<Future<T>> | invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) | |
Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires, whichever happens first. | 执行给定的任务,当所有任务完成或超时过期(以先发生的为准)时,返回一个保存其状态和结果的未来列表。 | |
<T> T | invokeAny(Collection<? extends Callable<T>> tasks) | |
Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do. | 执行给定的任务,返回已成功完成的任务的结果(即,不引发异常),如果有的话。 | |
<T> T | invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) | |
Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do before the given timeout elapses. | 执行给定的任务,如果在给定的超时时间过去之前执行任何操作,则返回已成功完成的任务的结果(即,不引发异常)。 | |
boolean | isShutdown() | |
Returns true if this executor has been shut down. | 返回true;如果此执行器已关闭。 | |
boolean | isTerminated() | |
Returns true if all tasks have completed following shut down. | 如果关闭后所有任务都已完成,则返回true。 | |
void | shutdown() | |
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. | 启动有序关闭,其中执行以前提交的任务,但不接受新任务。 | |
List<Runnable> | shutdownNow() | |
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution. | 尝试停止所有正在执行的任务,停止正在等待的任务的处理,并返回正在等待执行的任务的列表。 | |
<T> Future<T> | submit(Callable<T> task) | |
Submits a value-returning task for execution and returns a Future representing the pending results of the task. | 提交一个返回值的任务以供执行,并返回一个表示任务挂起结果的Future。 | |
Future<?> | submit(Runnable task) | |
Submits a Runnable task for execution and returns a Future representing that task. | 提交可运行任务以执行,并返回表示该任务的Future。 | |
<T> Future<T> | submit(Runnable task, T result) | |
Submits a Runnable task for execution and returns a Future representing that task. | 提交可运行任务以执行,并返回表示该任务的Future。 |
二.实现一个功能案例
案例功能实现:使用多线程对指定一系列机器做ping网络检测,并输出检测结果。
基本思路:使用锁synchronized和volatile关键字来确保多线程环境中的数据操作安全,并结合java多线程api,实现快速的对一组机器做ping网络检测,并输出检测结果。
java实现:
package simple.callback.network;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @program: psimple
* @description:java多线程安全与关键字volatile/synchronized,Executors、ExecutorService
* @author: Mr.Wang
* @create: 2021年 01月 18日 星期一 22:55:22 CST
**/
public class PingNetworkV6 {
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
int ips = PingNetworkThread.allIp.size();
int threadnum = 15;//定长线程池线程数量
int runablecounts = 13;//待执行的任务数量
ExecutorService executorService = Executors.newFixedThreadPool(threadnum);
for (int i = 0; i < runablecounts; i++)
executorService.submit(new PingNetworkThread());
executorService.shutdown();
while (true) {
if (executorService.isTerminated() == true) {
long end = System.currentTimeMillis();
System.out.println();
System.out.println("[任务执行完毕]:" + ips + "个ip检测");
System.out.println("[ping成功ip串]:" + PingNetworkThread.ipsOK);
System.out.println("[ping失败ip串]:" + PingNetworkThread.ipsNO);
System.out.println(threadnum + "个线程异步执行" + runablecounts + "个任务,耗时:" + (end - start) + "ms");
break;
}
}
}
}
class PingNetworkThread extends Thread {
public volatile static Queue<String> allIp;
public volatile static String ipsOK = "";
public volatile static String ipsNO = "";
private String currentIp = "";
static {
allIp = new LinkedList<String>();
//已知ping的通的
allIp.offer("127.0.0.1");
allIp.offer("127.0.0.2");
//已知ping不通的
allIp.offer("192.168.0.0");
allIp.offer("192.168.1.109");
//再往队列新加几条ping不通的ip
allIp.offer("192.168.1.110");
allIp.offer("192.168.1.111");
allIp.offer("192.168.1.112");
allIp.offer("192.168.1.113");
allIp.offer("192.168.1.114");
allIp.offer("192.168.1.115");
allIp.offer("192.168.1.116");
allIp.offer("192.168.1.117");
allIp.offer("192.168.1.118");
allIp.offer("192.168.1.119");
allIp.offer("192.168.1.120");
/*for (int i = 120; i < 120 + 100; i++) {
allIp.offer("192.168.1." + i);
}*/
}
public PingNetworkThread() {
}
public PingNetworkThread(Queue<String> ipqueue) {
allIp = ipqueue;
}
public String getIp() {
String ip = null;
synchronized (allIp) {
ip = allIp.poll();
}
return ip;
}
@Override
public void run() {
while ((currentIp = getIp()) != null) {
try {
//System.out.println(Thread.currentThread().getName() + ",currentIp:" + currentIp);
if (PingUtils.ping(currentIp, 1)) {//把数值改小,包的个数
synchronized (PingNetworkThread.class) {
ipsOK += currentIp + ",";
System.out.println(Thread.currentThread().getName() + ",ping成功ip串:" + ipsOK);
}
} else {
synchronized (PingNetworkThread.class) {
ipsNO += currentIp + ",";
System.out.println(Thread.currentThread().getName() + ",ping失败ip串:" + ipsNO);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
程序执行输出:
pool-1-thread-2,ping成功ip串:127.0.0.2,
pool-1-thread-1,ping成功ip串:127.0.0.2,127.0.0.1,
pool-1-thread-9,ping失败ip串:192.168.1.114,
pool-1-thread-3,ping失败ip串:192.168.1.114,192.168.0.0,
pool-1-thread-4,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,
pool-1-thread-10,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,
pool-1-thread-11,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,
pool-1-thread-6,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,192.168.1.111,
pool-1-thread-5,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,192.168.1.111,192.168.1.110,
pool-1-thread-13,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,192.168.1.111,192.168.1.110,192.168.1.118,
pool-1-thread-7,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,192.168.1.111,192.168.1.110,192.168.1.118,192.168.1.112,
pool-1-thread-12,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,192.168.1.111,192.168.1.110,192.168.1.118,192.168.1.112,192.168.1.117,
pool-1-thread-8,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,192.168.1.111,192.168.1.110,192.168.1.118,192.168.1.112,192.168.1.117,192.168.1.113,
pool-1-thread-2,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,192.168.1.111,192.168.1.110,192.168.1.118,192.168.1.112,192.168.1.117,192.168.1.113,192.168.1.119,
pool-1-thread-1,ping失败ip串:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,192.168.1.111,192.168.1.110,192.168.1.118,192.168.1.112,192.168.1.117,192.168.1.113,192.168.1.119,192.168.1.120,
[任务执行完毕]:15个ip检测
[ping成功ip串]:127.0.0.2,127.0.0.1,
[ping失败ip串]:192.168.1.114,192.168.0.0,192.168.1.109,192.168.1.115,192.168.1.116,192.168.1.111,192.168.1.110,192.168.1.118,192.168.1.112,192.168.1.117,192.168.1.113,192.168.1.119,192.168.1.120,
15个线程异步执行13个任务,耗时:1123ms
Process finished with exit code 0
功能案例完整源码下载:
链接二: https://pan.baidu.com/s/1-OnZ4BGubOC5O-BaeKp_aA 提取码: ezpg