《Android 应用案例开发大全(第二版)》——2.7节线程相关类

简介:

本节书摘来自异步社区《Android 应用案例开发大全(第二版)》一书中的第2章,第2.7节线程相关类 ,作者 吴亚峰 , 于复兴 , 杜化美,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.7 线程相关类
Android 应用案例开发大全(第二版)
上一节详细介绍了绘制相关类,使读者对本案例的开发有了进一步的理解,在这一节将对线程相关类的开发进行详细介绍。前面已经完成了对水族馆背景及水族馆中鱼、鱼群和气泡绘制的开发,但是只是将鱼、鱼群、气泡绘制出来是远远不够的,还要让它们动起来,从而产生更加真实的效果。

本案例中启动了多个线程来定时刷新它们的位置。线程相关类主要包括气泡移动线程类、群鱼游动线程类、鱼群游动线程类、鱼食游动线程类和吸引力线程类,下面就对线程相关类的开发进行详细介绍。

2.7.1 气泡移动线程类——BubbleThread
首先介绍的是气泡移动线程类BubbleThread,该类的作用是使气泡不断地从屏幕前面冒出来,在上升一段距离后会消失,然后再在随机的位置产生气泡重复上述运动,具体代码如下所示。

1 package com.bn.ld.WorksThread;
2 ……//此处省略部分类和包的引入代码,读者可自行查阅光盘中的源代码
3 public class BubbleThread extends Thread {
4  boolean flag = true;        // 标志位
5  BubbleControl Bcl;        // 气泡的控制类
6  public BubbleThread(BubbleControl Bcl) {
7   this.Bcl=Bcl;
8  }
9  public void run(){
10   while (flag) {        // 标志位
11    try {
12     for(int i=0;i<Bcl.BubbleSingle.size();i++){ // 遍历气泡列表
13       Bcl.BubbleSingle.get(i).bubbleMove();                // 执行气泡移动的方法
14     }
15    } catch (Exception e) {     // 进行异常处理
16     e.printStackTrace();     // 打印异常
17    }try {
18     Thread.sleep(100);     // 线程休眠100ms
19    } catch (Exception e) {     // 异常处理
20     e.printStackTrace();     // 打印异常
21 }}}}

说明
该类是气泡移动线程类,在该类中遍历气泡列表BubbleSingle,并调用气泡的移动方法bubbleMove,然后让线程休眠100ms后刷新气泡。

2.7.2 群鱼游动线程类——FishGoThread
上一小节完成了气泡移动线程类的介绍,读者已经了解了使气泡移动的方法。本小节将着重介绍群鱼移动线程类FishGoThread,具体包括群鱼之间的受力算法,群鱼碰到鱼群时的受力变化,以及群鱼和墙壁碰撞时的群鱼受力情况,具体代码如下所示。

1 package com.bn.ld.WorksThread;
2 ……//此处省略部分类和包的引入代码,读者可自行查阅光盘中的源代码
3 public class FishGoThread extends Thread {  // 定时运动所有群鱼的线程
4  public void run() {
5   while (flag) {
6   try {        // 动态地修改群鱼受到的力的大小
7    for (int i = 0; i < fishControl.fishAl.size(); i++) {              // 计算其他鱼对该鱼产生的力的大小
8     Vector3f Vwall = null;
9     inside: for (int j = 0; j < fishControl.fishAl.size(); j++) {
10      Vector3f V3 = null;
11      if (i == j) {   // 自己不能对自己产生力
12     continue inside; 
13    }
14    V3 = fishControl.fishAl.get(i).position.cut(                // 向量减法得到力的改变方向
15     fishControl.fishAl.get(j).position,Constant.MinDistances);
16    V3.getforce(fishControl.fishAl.get(i).weight); // 力与质量的比
17    fishControl.fishAl.get(i).force.plus(V3);  // 两条鱼之间的力
18    }
19  if (fishControl.Tr.fishSchool != null&& fishControl.Tr.fishSchool.fishSchool.   
  size() != 0) {
20    Vector3f V4 = fishControl.fishAl.get(i).position.cut(               // 向量减法得到力的方向
21     fishControl.Tr.fishSchool.fishSchoolget(0).position,   
     Constant.MinDistances);
22    V4.getforce(fishControl.fishAl.get(i).weight);
23    fishControl.fishAl.get(i).force.plus(V4);  // 两条鱼之间的力
24  }
25  Vwall = new Vector3f(0, 0, 0);
26  if (fishControl.fishAl.get(i).position.x <= -12f) { // 判断鱼和左墙壁的碰撞
27   Vwall.x = 0.0013215f;      // 撞上之后产生的力的作用
28  }
29  if (fishControl.fishAl.get(i).position.x > 12f) { // 判断鱼和右墙壁的碰撞
30   Vwall.x = -0.0013212f;      // 撞上之后产生的力的作用
31  }
32  if (fishControl.fishAl.get(i).position.y >= 4f) { // 判断鱼和上墙壁的碰撞
33   Vwall.y = -0.0013213f;      // 撞上之后产生的力的作用
34  }
35  if (fishControl.fishAl.get(i).position.y <= -3) { // 判断鱼和下墙壁的碰撞
36   Vwall.y = 0.002214f;       // 撞上之后产生的力的作用
37   if(fishControl.fishAl.get(i).position.y < -4){ // 鱼和下墙壁太近
38    Vwall.y = 0.006428f;      // 鱼所受到的反向力加倍
39   }}
40  if (fishControl.fishAl.get(i).position.z < -9f) { // 判断鱼和后墙壁的碰撞
41   Vwall.z = 0.0014214f;      // 撞上之后产生的力的作用
42  }
43  if (fishControl.fishAl.get(i).position.z > 1) {  // 判断鱼和前墙壁的碰撞
44   Vwall.z = -0.002213f;      // 撞上之后产生的力的作用
45  }
46  Vwall.y -= 0.000009;
47  fishControl.fishAl.get(i).force.plus(Vwall); // 鱼所受的力与墙给的力相加
48  }
49  for (int i = 0; i < fishControl.fishAl.size(); i++) {// 定时修改鱼的速度和位移
50   fishControl.fishAl.get(i).fishMove();   // 调用鱼游动方法的作用
51  }
52  } catch (Exception e) {       // 异常处理
53   e.printStackTrace();
54  }
55  try {           // 线程休眠
56   Thread.sleep(100);
57  } catch (Exception e) {       // 异常处理
58   e.printStackTrace();
59  }}}}

第3~24行计算单条鱼所受到的其他鱼的力,和鱼群对该鱼的力。当鱼与其他单条鱼或鱼群中鱼之间的距离小于阈值后会产生力的作用。
第25~48行是鱼与上、下、左、右、前、后墙壁的碰撞检测,碰撞时会产生力的作用。然后将鱼所受到的力与墙壁给鱼的力相加求出鱼所受到的合力。
第49~59行修改所有鱼的速度和位移。遍历群鱼列表,调用fishMove方法,让线程休眠100ms后刷新群鱼。

2.7.3 鱼群游动线程类——FishSchoolThread
上一小节详细介绍了群鱼游动线程类,本小节主要介绍鱼群游动线程类FishSchoolThread,具体包括鱼群之间的受力算法,鱼群碰到群鱼之后的受力变化,以及鱼群和墙壁碰撞时的鱼群受力情况,具体代码如下所示。

1 package com.bn.ld.WorksThread;
2 ……//此处省略部分类和包的引入代码,读者可自行查阅光盘中的源代码
3 public class FishschoolThread extends Thread {
4  boolean flag = true;       // 线程标志位
5  FishSchoolControl fishschools;     // 鱼群控制类对象
6  float Length;        // 两条鱼之间的距离
7  public FishschoolThread(FishSchoolControl fishschools) {
8   this.fishschools = fishschools;
9  }
10  public void run() {
11  while (flag) {        // 定时移动鱼类
12  try {          // 鱼群受力
13  outside: for (int i = 1; i < fishschools.fishSchool.size(); i++) {               // 群鱼对鱼群里面的鱼的作用力
14  for (int j = 0; j < fishschools.Tr.fishControl.fishAl.size(); j++) {
15   if (Length > Constant.SMinDistaces-0.5) { // 距离超过一定范围就不受力
16    continue outside;
17   }
18   Vector3f V3 = null;.
19   V3 = fishschools.fishSchool.get(i).position.cut(
20    fishschools.Tr.fishControl.fishAl.get(j).position,
21    Constant.SMinDistaces);   // 进行向量减法获得力的方向
22   V3.getforce(Constant.WeightScals); // 力的缩放比,等同于单个鱼的质量
23   fishschools.fishSchool.get(i).force.plus(V3); // 两条鱼之间的力
24  }}
25  Vector3f Vwall = null;
26  float Cx = fishschools.fishSchool.get(0).position.x; // 第1条鱼的当前位置
27  float Cy = fishschools.fishSchool.get(0).position.y;
28  float Cz = fishschools.fishSchool.get(0).position.z;
29  int j=1;
30  for(int i=-90;i<=90.;i=i+90){     // 鱼群里面3条受群鱼力的鱼
31   fishschools.fishSchool.get(j).ConstantPosition.x = (float) (Cx+  
   Constant.Radius*Math.cos(i));
32   fishschools.fishSchool.get(j).ConstantPosition.y = Cy;
33   fishschools.fishSchool.get(j).ConstantPosition.z = (float) (Cz+  
  Constant.Radius*Math.sin(i));
34   j++;
35  }
36  for (int i = 1; i < fishschools.fishSchool.size(); i++){                // 每条鱼受到的恒力(不包括第1条鱼)
37  Vector3f VL = null;
38  VL = fishschools.fishSchool.get(i).ConstantPosition
39   .cutGetforce(fishschools.fishSchool.get(i).position);                // 计算恒力的中间变量
40  Length = VL.Vectormodule();     // 计算距离
41  if ((Length) >= Constant.SMinDistaces){
42   VL.getforce(Constant. ConstantForceScals / 8f);// 距离太远,那么恒力会增加
43  }else if (Length<= 0.3){     // 距离小于某个值时不产生力
44   VL.x = VL.y = VL.z = 0;
45  } else{
46   VL.getforce(Constant. ConstantForceScals);
47  }
48  float MediaLength = fishschools.fishSchool.get(i).force.Vectormodule();
49  if (Math.abs(MediaLength) == 0) {  // 把计算得到的力赋给恒力ConstantForce
50   fishschools.fishSchool.get(i).ConstantForce.x = VL.x;
51   fishschools.fishSchool.get(i).ConstantForce.y = VL.y;
52   fishschools.fishSchool.get(i).ConstantForce.z = VL.z;
53  } else {       // 把计算得到的力赋给恒力ConstantForce
54   fishschools.fishSchool.get(i).ConstantForce.x = 0;
55   fishschools.fishSchool.get(i).ConstantForce.y = 0;
56   fishschools.fishSchool.get(i).ConstantForce.z = 0;
57  }}
58  Vwall = new Vector3f(0, 0, 0);     // 判断鱼和墙壁的碰撞
59  if (fishschools.fishSchool.get(0).position.x <= -9) {
60   Vwall.x = 0.0013215f;     // 鱼与左墙壁的碰撞
61  } 
62  if (fishschools.fishSchool.get(0).position.x > 9) {
63   Vwall.x = -0.0013212f;     // 鱼与右墙壁的碰撞
64  }
65  if (fishschools.fishSchool.get(0).position.y >= 9) {
66   Vwall.y = -0.0013213f;     // 鱼与上墙壁的碰撞
67  }
68  if (fishschools.fishSchool.get(0).position.y <= -6) {
69   Vwall.y = 0.002214f;      // 鱼与下墙壁的碰撞
70  }
71  if (fishschools.fishSchool.get(0).position.z < -7) {
72   Vwall.z = 0.0014214f;     // 鱼与后墙壁的碰撞
73  }
74  if (fishschools.fishSchool.get(0).position.z > 4) {
75   Vwall.z = -0.002213f;     // 鱼与前墙壁的碰撞
76  }
77  fishschools.fishSchool.get(0).force.plus(Vwall);
78  for (int i = 0; i < fishschools.fishSchool.size(); i++) {                // 定时修改鱼的速度和位移
79   fishschools.fishSchool.get(i).fishschoolMove();
80  }
81  } catch (Exception e) {      // 异常处理
82   e.printStackTrace();      // 打印异常
83  }try {
84   Thread.sleep(100);      // 线程休眠
85  } catch (Exception e) {      // 异常处理
86   e.printStackTrace();
87 }}}}

第11~35行计算群鱼对鱼群的作用力。当鱼群中的某条鱼与群鱼的距离小于阈值后便对该鱼产生力的作用。本案例将鱼群中的第一条鱼设置为不受其他任何鱼的力,只受到墙壁力的作用。鱼群中其他的3条鱼(不包括第1条鱼)之间没有力的作用,也不受到第一条鱼的作用力,但是受到从该条鱼位置指向相对位置(以鱼群中第一条鱼所在位置为球心,以定长半径确定的球面上的一个点)的力的作用,同时也会受到群鱼的作用力。
第36~57行给离开鱼群的鱼赋予一个恒力。一旦这条鱼相对脱离了鱼群之后就会受到一个恒力使这条鱼游回鱼群,该条鱼游得越远这个力就会越大,从而使鱼群里面的鱼能够快速回到鱼群。
第58~76行是鱼群里面第一条鱼与上、下、左、右、前、后墙壁的碰撞检测,碰撞时会对鱼群里面的第一条鱼产生力的作用。
第77~87行为修改鱼群里面所有鱼的速度和位移。调用每条鱼的fishschoolMove方法定时修改鱼群里面鱼的速度和位移。进行异常处理,让线程休眠100ms后刷新鱼群。

2.7.4 鱼食移动线程类——FoodThread
上一小节完成了鱼群移动线程类的介绍,读者已经了解了使鱼群移动的方法。本小节着重介绍鱼食移动线程类FoodThread,主要包括食物的移动方法和标志位的设置,具体代码如下所示。

1 package com.bn.ld.WorksThread;
2 ……// 此处省略部分类和包的引入代码,读者可自行查阅光盘中的源代码
3 public class FoodThread extends Thread {   // 定时运动食物的线程
4  public boolean flag1 = true    // 线程的标志位
5     public boolean Fresit=true;    // 食物的_y_是否重置的标志位
6  boolean FxMove=true;      // 移动_x_方向的标志位
7  public boolean Go=false;     // 线程里面的算法,是否走的标志位
8  public  SingleFood SingleF;    // SingleFood对象的引用
9  public FoodThread(SingleFood singleF){
10   this.SingleF=singleF;
11  }
12  public void run(){
13   while (flag1) {
14    try {
15     if(Go){
16      if{(FxMove)   /食物晃动的标志位
17       SingleF.Tr.Xposition+= FoodMove_X;
18       FxMove=!FxMove;
19      }
20      else{
21       SingleF.Tr.Xposition-= FoodMove_X;
22       FxMove=!FxMove;
23      }
24      SingleF.Ypositon-= Constant.FoodSpeed;               // 定时地修该_y_坐标
25     }}
26    catch (Exception e) {
27     e.printStackTrace();   // 打印异常
28    }
29    try {
30     Thread.sleep(200);   // 线程休眠
31    } catch (Exception e) {
32     e.printStackTrace();   // 打印异常
33    }}}}

说明
该类是鱼食移动线程类,本案例中的鱼食是从上到下匀速运动,并且每次计算食物y所在的位置之前,会通过增加或减少食物的x、z坐标来使食物产生轻微的晃动效果,从而增强食物的真实感,让线程休眠200ms后刷新鱼食。

2.7.5 吸引力线程类——AttractThread
上一小节介绍了食物移动线程类。本节主要介绍鱼食对群鱼的吸引力线程类AttractThread,本案例中鱼群里面的鱼是看不到鱼食的,即不会受到食物吸引力的作用,具体代码如下所示。

1 package com.bn.ld.WorksThread;
2  ……//此处省略部分类和包的引入代码,读者可自行查阅光盘中的源代码
3 public class AttractThread extends Thread {   // 定时运动鱼群的线程
4  public boolean Feeding = true;     // 线程的标志位
5  public boolean Fforcefish = true;    // 清空列表标志位
6  public boolean Go = false;      // 计算吸引力的标志位
7  float Length;        // 力的模长
8  SingleFood Sf;
9  ArrayList<SingleFish> fl = new ArrayList<SingleFish>(); // 受到力的鱼列表
10  public AttractThread(SingleFood sf) {
11   this.Sf = sf;
12  }
13  public void run() {
14   while (Feeding) {     // Feeding为永真
15    try {
16    if (Go) {      // 寻找能看到食物的鱼,添加到列表
17     if (Fforcefish) {    // 每次在点击喂食时要把列表清空
18      fl.clear();   // 清空列表
19      Fforcefish = false; // 只清空一次
20    }
21   if (fl != null ) {
22   for (int i = 0; i < Sf.Tr.fishAl.size(); i++) {  // 寻找满足条件的鱼
23   if (Sf.Tr.fishAl.get(i).position.x > Sf.Tr.Xposition&& Sf.Tr.fishAl.   
   get(i).speed.x < 0) {
24    if (!fl.contains(Sf.Tr.fishAl.get(i))) {
25     fl.add(Sf.Tr.fishAl.get(i));
26    }}
27   else if (Sf.Tr.fishAl.get(i).position.x < Sf.Tr.Xposition&& Sf.Tr.   
   fishAl.get(i).speed.x > 0) {
28    if (!fl.contains(Sf.Tr.fishAl.get(i))) {
29     fl.add(Sf.Tr.fishAl.get(i));
30     }}}}
31    if (fl.size() != 0) {    // 给鱼加食物时吸引力的作用
32     for (int i = 0; i < fl.size(); i++) {
33     Vector3f VL = null;     // 计算吸引力的中间变量
34     Vector3f Vl2 = null;     // 食物的位置信息
35     Vl2 = new Vector3f(Sf.Tr.Xposition,Sf.Tr.singleFood.       Ypositon,Sf.Tr.Zposition);
36     VL = Vl2.cutPc(fl.get(i).position); // 获取需要的向量
37     Length = VL.Vectormodule();   // 吸引力的模长
38       if (Length != 0) {
39       VL.ChangeStep(Length); // 将力的大小规格化
40      }
41   if (Length <= Constant.FoodFeedDistance || Sf.Ypositon < Constant.  
   FoodPositionMin_Y) {
42       StopAllThread();
43      }
44     VL.getforce(Constant.AttractForceScals); // 吸引力的缩放比例
45     fl.get(i).attractforce.x = VL.x;                  // 把计算得到的吸引力赋给食物吸引力
46     fl.get(i).attractforce.y = VL.y;
47     fl.get(i).attractforce.z = VL.z;
48     }}}
49     if (Sf.Ypositon < Constant.FoodPositionMin_Y)) {              // 判断Ypositon是否超出范围
50      StopAllThread();
51     }
52    } catch (Exception e) {     // 异常处理
53     e.printStackTrace();     // 打印异常
54    }
55    try {         // 线程休眠
56     Thread.sleep(100);
57    } catch (Exception e) {     // 异常处理
58     e.printStackTrace();     // 打印异常
59    }}}
60  public void StopAllThread() {
61   Sf.Ypositon = Constant.FoodPositionMin_Y);  // 重置Ypositon
62   this.Fforcefish = true;         // 清空受到吸引力的鱼列表
63   this.Go = false;       // 吸引力算法的标志位
64   Sf.Ft.Go = false;       // 食物移动的标志位
65   Constant.isFeed = true;       // 喂食的标志位为ture
66   }}

第4~12行为设置线程标志位、是否清空受到食物吸引力的鱼列表的标志位(每次喂食之前会清空列表fl)、是否计算食物吸引力的标志位。并创建受到食物吸引力的鱼列表。
第14~30行寻找能看到鱼食的鱼,每喂食一次清空受到吸引力的鱼列表fl,然后再次喂食的时候会重新寻找满足条件的鱼,如果满足条件把该条鱼添加到受到吸引力的鱼列表fl里。
第31~51行为计算列表fl里面鱼受到食物吸引力的算法,能看到鱼食的鱼受到一个由该鱼当前位置指向食物的吸引力作用。
第60~66行为StopAllThread方法,若鱼食位置超过地面,或者鱼食被鱼吃掉之后,就会调用此方法,把鱼食移动线程里面的计算标志位和计算群鱼是否受到的食物吸引力标志位变为false,同时把点击喂食的标志位设置为true,从而能点击屏幕再次喂食。

相关文章
|
22小时前
|
缓存 Java Android开发
构建高效的Android应用:内存优化策略解析
【5月更文挑战第25天】在移动开发领域,性能优化一直是一个不断探讨和精进的课题。特别是对于资源受限的Android设备来说,合理的内存管理直接关系到应用的流畅度和用户体验。本文深入分析了Android内存管理的机制,并提出了几种实用的内存优化技巧。通过代码示例和实践案例,我们旨在帮助开发者识别和解决内存瓶颈,从而提升应用性能。
|
1天前
|
移动开发 Android开发 开发者
构建高效Android应用:Kotlin与协程的完美融合
【5月更文挑战第25天】 在移动开发的世界中,性能和响应性是衡量应用质量的关键指标。随着Kotlin的流行和协程的引入,Android开发者现在有了更强大的工具来提升应用的性能和用户体验。本文深入探讨了Kotlin语言如何与协程相结合,为Android应用开发带来异步处理能力的同时,保持代码的简洁性和可读性。我们将通过实际案例分析,展示如何在Android项目中实现协程,以及它们如何帮助开发者更有效地管理后台任务和用户界面的流畅交互。
|
1天前
|
调度 数据库 Android开发
构建高效Android应用:Kotlin协程的全面应用
【5月更文挑战第25天】随着移动开发技术的不断进步,Android开发者寻求更高效的异步处理解决方案以提升应用性能和用户体验。Kotlin协程作为一种轻量级的线程管理机制,在简化异步编程、提升响应速度以及降低资源消耗方面展现出独特的优势。本文将深入探讨Kotlin协程的核心原理,并通过实例演示如何在Android应用中有效地利用协程来处理网络请求、数据库操作以及UI线程的流畅交互,旨在为开发者提供一套系统的应用实践指南。
|
1天前
|
安全 Java 大数据
Java多线程编程:深入理解与应用
Java多线程编程:深入理解与应用
|
1天前
|
缓存 监控 Java
安卓应用开发中的内存优化策略
【5月更文挑战第24天】 在移动设备上,资源的有限性要求开发者对应用程序进行细致入微的性能优化。特别是对于安卓平台,由于设备的多样性和碎片化问题,内存管理成为提升应用性能、用户体验和电池寿命的关键因素。本文将探讨针对安卓开发的内存优化技巧,从避免内存溢出、减少内存占用到提高内存回收效率等方面展开讨论,旨在为开发者提供实用的内存优化策略,以改善应用的运行效率和稳定性。
|
2天前
|
安全 Go 对象存储
C++多线程编程:并发与同步的实战应用
本文介绍了C++中的多线程编程,包括基础知识和实战应用。C++借助`&lt;thread&gt;`库支持多线程,通过`std::thread`创建线程执行任务。文章探讨了并发与同步的概念,如互斥锁(Mutex)用于保护共享资源,条件变量(Condition Variable)协调线程等待与通知,以及原子操作(Atomic Operations)保证线程安全。实战部分展示了如何使用多线程进行并发计算,利用`std::async`实现异步任务并获取结果。多线程编程能提高效率,但也需注意数据竞争和同步问题,以确保程序的正确性。
|
3天前
|
数据库 Android开发 UED
构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第23天】在移动开发领域,性能优化和响应性是至关重要的。随着Kotlin成为Android官方推荐的开发语言,其提供的协程功能为异步编程带来了革命性的改进。本文将深入探讨Kotlin协程的核心优势,并通过实例演示如何在Android应用中有效利用协程来提升性能和用户体验。
|
3天前
|
数据库 Android开发 开发者
构建高效的Android应用:Kotlin协程的优势与实践
【5月更文挑战第23天】 在移动开发领域,性能优化和流畅的用户体验始终是开发者追求的目标。随着Kotlin语言在Android平台的广泛采用,其提供的协程功能已成为提升应用性能的强大工具。本文将深入探讨Kotlin协程的核心优势,并通过具体实例展示如何在Android应用中高效地运用协程进行异步编程,以及如何通过协程简化后台任务处理,实现流畅的用户界面。
|
3天前
|
移动开发 数据处理 Android开发
构建高效Android应用:Kotlin的协程与Flow的使用
【5月更文挑战第23天】 在移动开发领域,性能优化和异步编程一直是核心议题。随着Kotlin语言在Android开发中的普及,其提供的协程(coroutines)和流式编程(Flow)功能为开发者带来了革命性的工具,以更简洁、高效的方式处理异步任务和数据流。本文将深入探讨Kotlin协程和Flow在Android应用中的实际应用,以及它们如何帮助开发者编写更加响应迅速且不阻塞用户界面的应用程序。我们将通过具体案例分析这两种技术的优势,并展示如何在现有项目中实现这些功能。
|
3天前
|
Java
【JAVA学习之路 | 提高篇】创建与启动线程之二(继承Thread类)(实现Runnable接口)
【JAVA学习之路 | 提高篇】创建与启动线程之二(继承Thread类)(实现Runnable接口)