Java和 Android 多线程编程中的 Runnable、Callable、Future、Executor
多线程是一种Java功能,它允许同时执行程序的两个或多个部分,以最大限度地利用 CPU。这样一个程序的每个部分都称为一个线程。因此,线程是进程中的轻量级进程。
可运行
任何其实例打算由线程执行的类都应实现 Runnable 接口。该类必须定义一个不带参数的运行方法。此接口旨在为希望在活动时运行代码的对象提供标准协议。例如,Thread 实现了 Runnable 接口。处于活动状态仅仅意味着线程已经开始并且尚未终止。此外,Runnable 允许一个类在不继承 Thread 的情况下处于活动状态。实现 Runnable 的类可以通过创建 Thread 实例并将自身作为目标传递而无需子类化 Thread 即可执行代码。
要使用 Runnable 创建新线程,请执行以下步骤:
- 创建一个 Runnable 实现者并调用 run() 方法。
- 创建一个 Thread 实例并将实现者传递给它。 Thread 有一个接受 Runnable 实例的函数Object() { [native code] }。
- 在 Thread 实例上调用 start(); start 在内部调用实现者的 run()。调用 start() 会生成一个执行 run() 中指定的代码的新线程。
Java
public class Comment implements Activity {
private Date GeeksCreatedAt;
public Comment(Date GeeksCreatedAt)
{
this.GeeksCreatedAt = GeeksCreatedAt;
}
@Override public Date getCoursesAddedAt()
{
return GeeksCreatedAt;
}
@Override public String toString()
{
return "Comment{"
+ "GeeksCreatedAt=" + GeeksCreatedAt + '}';
}
}
public class GfG implements Activity {
private Date GeeksCreatedAt;
public GfG(Date GeeksCreatedAt)
{
this.GeeksCreatedAt = GeeksCreatedAt;
}
@Override public Date getCoursesAddedAt()
{
return GeeksCreatedAt;
}
@Override public String toString()
{
return "GfG{"
+ "GeeksCreatedAt=" + GeeksCreatedAt + '}';
}
}
Java
public class Like implements Activity {
private Date GeeksCreatedAt;
public Like(Date GeeksCreatedAt)
{
this.GeeksCreatedAt = GeeksCreatedAt;
}
@Override public Date getCreatedAt()
{
return GeeksCreatedAt;
}
@Override public String toString()
{
return "Like{"
+ "GeeksCreatedAt=" + GeeksCreatedAt + '}';
}
}
Java
public class Post implements Activity {
private Date GeeksCreatedAt;
public Post(Date GeeksCreatedAt)
{
this.GeeksCreatedAt = GeeksCreatedAt;
}
@Override public Date getCreatedAt()
{
return GeeksCreatedAt;
}
@Override public String toString()
{
return "Post{"
+ "GeeksCreatedAt=" + GeeksCreatedAt + '}';
}
}
Java
public class RemoteService {
private static int cores
= Runtime.getRuntime().availableProcessors();
private static ExecutorService executor
= Executors.newFixedThreadPool(cores + 1);
public void stop() { executor.shutdown(); }
public void
getUserRecentGfgActs(ResultCallback callback)
{
executor.execute(() -> {
List gfgLikes = new ArrayList<>();
List gfgPOsts = new ArrayList<>();
List comments = new ArrayList<>();
List gfgCourses = new ArrayList<>();
Future > futureGfgLikes
= executor.submit(getGfgLikes(
"https://geeksforgeeks.org.com/gfgLikes"));
Future > futureComments
= executor.submit(getComments(
"https://geeksforgeeks.org.com/comments"));
Future > futureGfgPOsts
= executor.submit(getGfgPOsts(
"https://geeksforgeeks.org.com/gfgPOsts"));
Future > futureGfgCourses
= executor.submit(getGfgCourses(
"https://geeksforgeeks.org.com/gfgCourses"));
try {
gfgLikes = futureGfgLikes.get();
}
catch (InterruptedException
| ExecutionException e) {
e.printStackTrace();
}
try {
gfgPOsts = futureGfgPOsts.get();
}
catch (InterruptedException
| ExecutionException e) {
e.printStackTrace();
}
try {
comments = futureComments.get();
}
catch (InterruptedException
| ExecutionException e) {
e.printStackTrace();
}
try {
gfgCourses = futureGfgCourses.get();
}
catch (InterruptedException
| ExecutionException e) {
e.printStackTrace();
}
List gfgActs = new ArrayList<>();
gfgActs.addAll(gfgLikes);
gfgActs.addAll(gfgPOsts);
gfgActs.addAll(comments);
gfgActs.addAll(gfgCourses);
Collections.sort(
gfgActs,
(activity1, activity2)
-> activity1.getCreatedAt().compareTo(
activity2.getCreatedAt()));
callback.onResult(gfgActs);
});
}
private Callable > getGfgLikes(String url)
{
return () ->
{
System.out.println("getGfgLikes");
Thread.sleep(200);
return Arrays.asList(
new Like(new Date(1534334348560L)),
new Like(new Date(1554365436546960L)));
};
}
private Callable > getGfgPOsts(String url)
{
return () ->
{
System.out.println("getGfgPOsts");
Thread.sleep(500);
return Arrays.asList(
new Post(new Date(15334343448560L)),
new Post(new Date(153343434460L)));
};
}
private Callable > getComments(String url)
{
return () ->
{
System.out.println("getComments");
Thread.sleep(200);
return Arrays.asList(
new Comment(new Date(15356565648560L)),
new Comment(new Date(151454545456460L)));
};
}
private Callable >
getGfgCourses(String url)
{
return () ->
{
System.out.println("getGfgCourses");
Thread.sleep(6500);
return Arrays.asList(
new Friend(new Date(1534543354248560L)),
new Friend(new Date(15334343546460L)));
};
}
}
可调用
产生结果并有能力抛出异常的任务。实现者定义了一个名为 call 的方法,它不接受任何参数。 Callable 接口与 Runnable 接口相似,两者都适用于其实例可能由另一个线程执行的类。另一方面,Runnable 不返回值,也不能抛出检查异常。 Executors 包含用于从其他常见形式转换为 Callable 类的实用方法。为了实现 Runnable,必须实现 run() 方法,该方法不返回任何内容,而为了实现 Callable,必须实现 call() 方法,该方法在完成时返回结果。需要注意的是,不能使用 Callable 创建线程;只有 Runnable 可以这样做。另一个区别是 call() 方法可以抛出异常,而 run() 方法不能。
Java
public class Like implements Activity {
private Date GeeksCreatedAt;
public Like(Date GeeksCreatedAt)
{
this.GeeksCreatedAt = GeeksCreatedAt;
}
@Override public Date getCreatedAt()
{
return GeeksCreatedAt;
}
@Override public String toString()
{
return "Like{"
+ "GeeksCreatedAt=" + GeeksCreatedAt + '}';
}
}
Java
public class Post implements Activity {
private Date GeeksCreatedAt;
public Post(Date GeeksCreatedAt)
{
this.GeeksCreatedAt = GeeksCreatedAt;
}
@Override public Date getCreatedAt()
{
return GeeksCreatedAt;
}
@Override public String toString()
{
return "Post{"
+ "GeeksCreatedAt=" + GeeksCreatedAt + '}';
}
}
未来
Future 是异步计算的结果。提供了确定计算是否完成、等待其完成以及检索计算结果的方法。计算完成后,只能使用 get 方法检索结果,必要时阻塞,直到它准备好。 cancel 方法用于取消事务。提供了额外的方法来确定任务是否正常完成。一旦计算完成,就不能取消。如果您想将 Future 用于可取消性但不提供可用结果,您可以声明 Future?类型并返回 null 作为底层任务的结果。因为它实现了 Future 接口,所以在线程启动后与线程的所有交互都由 FutureTask 对象处理。因此,无需保存 Thread 对象。 FutureTask 对象可用于取消任务、检查任务是否完成或尝试检索结果。
Java
public class RemoteService {
private static int cores
= Runtime.getRuntime().availableProcessors();
private static ExecutorService executor
= Executors.newFixedThreadPool(cores + 1);
public void stop() { executor.shutdown(); }
public void
getUserRecentGfgActs(ResultCallback callback)
{
executor.execute(() -> {
List gfgLikes = new ArrayList<>();
List gfgPOsts = new ArrayList<>();
List comments = new ArrayList<>();
List gfgCourses = new ArrayList<>();
Future > futureGfgLikes
= executor.submit(getGfgLikes(
"https://geeksforgeeks.org.com/gfgLikes"));
Future > futureComments
= executor.submit(getComments(
"https://geeksforgeeks.org.com/comments"));
Future > futureGfgPOsts
= executor.submit(getGfgPOsts(
"https://geeksforgeeks.org.com/gfgPOsts"));
Future > futureGfgCourses
= executor.submit(getGfgCourses(
"https://geeksforgeeks.org.com/gfgCourses"));
try {
gfgLikes = futureGfgLikes.get();
}
catch (InterruptedException
| ExecutionException e) {
e.printStackTrace();
}
try {
gfgPOsts = futureGfgPOsts.get();
}
catch (InterruptedException
| ExecutionException e) {
e.printStackTrace();
}
try {
comments = futureComments.get();
}
catch (InterruptedException
| ExecutionException e) {
e.printStackTrace();
}
try {
gfgCourses = futureGfgCourses.get();
}
catch (InterruptedException
| ExecutionException e) {
e.printStackTrace();
}
List gfgActs = new ArrayList<>();
gfgActs.addAll(gfgLikes);
gfgActs.addAll(gfgPOsts);
gfgActs.addAll(comments);
gfgActs.addAll(gfgCourses);
Collections.sort(
gfgActs,
(activity1, activity2)
-> activity1.getCreatedAt().compareTo(
activity2.getCreatedAt()));
callback.onResult(gfgActs);
});
}
private Callable > getGfgLikes(String url)
{
return () ->
{
System.out.println("getGfgLikes");
Thread.sleep(200);
return Arrays.asList(
new Like(new Date(1534334348560L)),
new Like(new Date(1554365436546960L)));
};
}
private Callable > getGfgPOsts(String url)
{
return () ->
{
System.out.println("getGfgPOsts");
Thread.sleep(500);
return Arrays.asList(
new Post(new Date(15334343448560L)),
new Post(new Date(153343434460L)));
};
}
private Callable > getComments(String url)
{
return () ->
{
System.out.println("getComments");
Thread.sleep(200);
return Arrays.asList(
new Comment(new Date(15356565648560L)),
new Comment(new Date(151454545456460L)));
};
}
private Callable >
getGfgCourses(String url)
{
return () ->
{
System.out.println("getGfgCourses");
Thread.sleep(6500);
return Arrays.asList(
new Friend(new Date(1534543354248560L)),
new Friend(new Date(15334343546460L)));
};
}
}
执行人
执行已提交的 Runnable 任务的对象。该接口允许您将任务提交与每个任务将如何执行的机制(例如线程使用、调度等)分离。通常使用 Executor 代替显式创建线程。例如,而不是调用 new Thread(new(RunnableTask()))。 start() 用于序列中的每个任务。顾名思义,它是一个具有固定数量线程的线程池。提交给 executor 的任务由 n 个线程执行,任何额外的任务都存储在 LinkedBlockingQueue 中。它采用阻塞队列。
创建并运行一个简单的执行器,我们将在其中创建一个任务并在固定池中运行它。
- Task 类实现 Callable 并具有 String 参数。还说会抛出异常。
- 要执行“Task”类中的任务,我们必须首先实例化 Task 类并将其传递给 executor 执行。
- Future 对象的结果应该被打印和显示。