Android(java)学习笔记62:关于多线程的实现(代码体现)

 1 package cn.itcast_02;
 2 
 3 /*
 4  * 该类要重写run()方法,为什么呢?
 5  * 不是类中的所有代码都需要被线程执行的。
 6  * 而这个时候,为了区分哪些代码能够被线程执行,java提供了Thread类中的run()用来包含那些被线程执行的代码。
 7  */
 8 public class MyThread extends Thread {
 9 
10     @Override
11     public void run() {
12         // 自己写代码
13         // System.out.println("好好学习,天天向上");
14         // 一般来说,被线程执行的代码肯定是比较耗时的。所以我们用循环改进
15         for (int x = 0; x < 200; x++) {
16             System.out.println(x);
17         }
18     }
19 
20 }

重写完这个MyThread这个类,我们接下来编写类,添加main方法,创建对象,调用这个类:

 

 1 package cn.itcast_02;
 2 
 3 /*
 4  * 需求:我们要实现多线程的程序。
 5  * 如何实现呢?
 6  *         由于线程是依赖进程而存在的,所以我们应该先创建一个进程出来。
 7  *         而进程是由系统创建的,所以我们应该去调用系统功能创建一个进程。
 8  *         Java是不能直接调用系统功能的,所以,我们没有办法直接实现多线程程序。
 9  *         但是呢?Java可以去调用C/C++写好的程序来实现多线程程序。
10  *         由C/C++去调用系统功能创建进程,然后由Java去调用这样的东西,
11  *         然后提供一些类供我们使用。我们就可以实现多线程程序了。
12  * 那么Java提供的类是什么呢?
13  *         Thread
14  *         通过查看API,我们知道了有2中方式实现多线程程序。
15  * 
16  * 方式1:继承Thread类。
17  * 步骤
18  *         A:自定义类MyThread继承Thread类。
19  *         B:MyThread类里面重写run()?
20  *             为什么是run()方法呢?
21  *         C:创建对象
22  *         D:启动线程
23  */
24 public class MyThreadDemo {
25     public static void main(String[] args) {
26         // 创建线程对象
27         // MyThread my = new MyThread();
28         // // 启动线程
29         // my.run();
30         // my.run();
31         // 调用run()方法为什么是单线程的呢?
32         // 因为run()方法直接调用其实就相当于普通的方法调用,所以你看到的是单线程的效果
33         // 要想看到多线程的效果,就必须说说另一个方法:start()
34         // 面试题:run()和start()的区别?
35         // run():仅仅是封装被线程执行的代码,直接调用是普通方法
36         // start():首先启动了线程,然后再由jvm去调用该线程的run()方法。
37         // MyThread my = new MyThread();
38         // my.start();
39         // // IllegalThreadStateException:非法的线程状态异常
40         // // 为什么呢?因为这个相当于是my线程被调用了两次。而不是两个线程启动。第一个已经start已经启动线程,第二个start再启动则会报错。
41         // my.start();
42 
43         // 创建两个不同线程对象
44         MyThread my1 = new MyThread();
45         MyThread my2 = new MyThread();
46 
47         my1.start();
48         my2.start();
49     }
50 }

执行代码我们看到了结果如下图:也许有人会问这个第一次运行的0,1,2,3……这样输出的是那个线程的?(my1还是my2线程的?),下面我们会回答这样的问题。

技术分享

 

针对刚刚我们提出的问题,我们来说明一下(我们用代码实现一下):

这个是我们写的一个线程类:

 1 package cn.itcast_03;
 2 
 3 public class MyThread extends Thread {
 4 
 5     public MyThread() {
 6     }
 7     
 8     public MyThread(String name){
 9         super(name);
10     }
11 
12     @Override
13     public void run() {
14         for (int x = 0; x < 100; x++) {
15             System.out.println(getName() + ":" + x);
16         }
17     }
18 }

下面我们再次写出测试类:

 1 package cn.itcast_03;
 2 
 3 /*
 4  * 如何获取线程对象的名称呢?
 5  * public final String getName():获取线程的名称。
 6  * 如何设置线程对象的名称呢?
 7  * public final void setName(String name):设置线程的名称
 8  * 
 9  * 针对不是Thread类的子类中如何获取线程对象名称呢?
10  * public static Thread currentThread():返回当前正在执行的线程对象
11  * Thread.currentThread().getName()
12  */
13 public class MyThreadDemo {
14     public static void main(String[] args) {
15         // 创建线程对象
16         //无参构造+setXxx()
17         // MyThread my1 = new MyThread();
18         // MyThread my2 = new MyThread();
19         // //调用方法设置名称
20         // my1.setName("林青霞");
21         // my2.setName("刘意");
22         // my1.start();
23         // my2.start();
24         
25         //带参构造方法给线程起名字
26         // MyThread my1 = new MyThread("林青霞");
27         // MyThread my2 = new MyThread("刘意");
28         // my1.start();
29         // my2.start();
30         
31         //我要获取main方法所在的线程对象的名称,该怎么办呢?
32         //遇到这种情况,Thread类提供了一个很好玩的方法:
33         //public static Thread currentThread():返回当前正在执行的线程对象
34         System.out.println(Thread.currentThread().getName());
35     }
36 }
37 
38 /*
39 名称为什么是:Thread-? 编号,下面是源码(注意这里我只是截取我需要的,方便理解和说明)
40 
41 class Thread {
42     private char name[];
43 
44     public Thread() {
45         init(null, null, "Thread-" + nextThreadNum(), 0);
46     }
47     
48     private void init(ThreadGroup g, Runnable target, String name,
49                       long stackSize) {
50         init(g, target, name, stackSize, null);
51     }
52     
53      private void init(ThreadGroup g, Runnable target, String name,
54                       long stackSize, AccessControlContext acc) {
55         //大部分代码被省略了
56         this.name = name.toCharArray();
57     }
58     
59     public final void setName(String name) {
60         this.name = name.toCharArray();
61     }
62     
63     
64     private static int threadInitNumber; //0,1,2
65     private static synchronized int nextThreadNum() {
66         return threadInitNumber++; //return 0,1
67     }
68     
69     public final String getName() {
70         return String.valueOf(name);
71     }
72 }
73 
74 class MyThread extends Thread {
75     public MyThread() {
76         super();
77     }
78 }
79 
80 */

附上执行效果图:

技术分享

 

这里不得不说这样的线程名字很没有针对性,大家说是不是?当然我们可以自己取线程的名字,调用setName()方法

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。