线程的创建方式和使用案例

 
多线程原理
昨天的时候我们已经写过一版多线程的代码,很多同学对原理不是很清楚,那么我们今天先画个多线程执行时序图
来体现一下多线程程序的执行流程。
代码如下:
自定义线程类:
public class MyThread extends Thread {
/*
* 利用继承中的特点
* 将线程名称传递 进行设置
*/
public MyThread ( String name ){
super ( name );
}
/*
* 重写 run 方法
* 定义线程要执行的代码
*/
public void run (){
for ( int i = 0 ; i < 20 ; i ++ ) {
//getName() 方法 来自父亲 北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
//getName() 方法 来自父亲
System . out . println ( getName () + i );
}
}
}
测试类:
public class Demo {
public static void main ( String [] args ) {
System . out . println ( " 这里是 main 线程 " );
MyThread mt = new MyThread ( " 小强 " );
mt . start (); // 开启了一个新的线程
for ( int i = 0 ; i < 20 ; i ++ ) {
System . out . println ( " 旺财 :" + i );
}
}
}
流程图: 北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
程序启动运行 main 时候, java 虚拟机启动一个进程,主线程 main main() 调用时候被创建。随着调用 mt 的对象的
start 方法,另外一个新的线程也启动了,这样,整个应用就在多线程下运行。
通过这张图我们可以很清晰的看到多线程的执行流程,那么为什么可以完成并发执行呢?我们再来讲一讲原理。
多线程执行时,到底在内存中是如何运行的呢?以上个程序为例,进行图解说明:
多线程执行时,在栈内存中,其实 每一个执行线程都有一片自己所属的栈内存空间 。进行方法的压栈和弹栈。
当执行线程的任务结束了,线程自动在栈内存中释放了。但是当所有的执行线程都结束了,那么进程就结束了。
1.2 Thread
在上一天内容中我们已经可以完成最基本的线程开启,那么在我们完成操作过程中用到了 java.lang.Thread 类,
API 中该类中定义了有关线程的一些方法,具体如下:
构造方法: 北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
public Thread() : 分配一个新的线程对象。
public Thread(String name) : 分配一个指定名字的新的线程对象。
public Thread(Runnable target) : 分配一个带有指定目标新的线程对象。
public Thread(Runnable target,String name) : 分配一个带有指定目标新的线程对象并指定名字。
常用方法:
public String getName() : 获取当前线程名称。
public void start() : 导致此线程开始执行 ; Java 虚拟机调用此线程的 run 方法。
public void run() : 此线程要执行的任务在此处定义代码。
public static void sleep(long millis) : 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
public static Thread currentThread() : 返回对当前正在执行的线程对象的引用。
翻阅 API 后得知创建线程的方式总共有两种,一种是继承 Thread 类方式,一种是实现 Runnable 接口方式  
1.3 创建线程方式二
采用 java.lang.Runnable 也是非常常见的一种,我们只需要重写 run 方法即可。
步骤如下:
1. 定义 Runnable 接口的实现类,并重写该接口的 run() 方法,该 run() 方法的方法体同样是该线程的线程执行体。
2. 创建 Runnable 实现类的实例,并以此实例作为 Thread target 来创建 Thread 对象,该 Thread 对象才是真正
的线程对象。
3. 调用线程对象的 start() 方法来启动线程。
代码如下:
public class MyRunnable implements Runnable {
@Override
public void run () {
for ( int i = 0 ; i < 20 ; i ++ ) {
System . out . println ( Thread . currentThread (). getName () + " " + i );
}
}
}
public class Demo {
public static void main ( String [] args ) {
// 创建自定义类对象 线程任务对象
MyRunnable mr = new MyRunnable ();
// 创建线程对象
Thread t = new Thread ( mr , " 小强 " );
t . start ();
for ( int i = 0 ; i < 20 ; i ++ ) {
System . out . println ( " 旺财 " + i );
}
}
} 北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
通过实现 Runnable 接口,使得该类有了多线程类的特征。 run() 方法是多线程程序的一个执行目标。所有的多线程
代码都在 run 方法里面。 Thread 类实际上也是实现了 Runnable 接口的类。
在启动的多线程的时候,需要先通过 Thread 类的构造方法 Thread(Runnable target) 构造出对象,然后调用 Thread
对象的 start() 方法来运行多线程代码。
实际上所有的多线程代码都是通过运行 Thread start() 方法来运行的。因此,不管是继承 Thread 类还是实现
Runnable 接口来实现多线程,最终还是通过 Thread 的对象的 API 来控制线程的,熟悉 Thread 类的 API 是进行多线程
编程的基础。
tips:Runnable 对象仅仅作为 Thread 对象的 target Runnable 实现类里包含的 run() 方法仅作为线程执行体。
而实际的线程对象依然是 Thread 实例,只是该 Thread 线程负责执行其 target run() 方法。
1.4 Thread Runnable 的区别
如果一个类继承 Thread ,则不适合资源共享。但是如果实现了 Runable 接口的话,则很容易的实现资源共享。
总结:
实现 Runnable 接口比继承 Thread 类所具有的优势:
1. 适合多个相同的程序代码的线程去共享同一个资源。
2. 可以避免 java 中的单继承的局限性。
3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
4. 线程池只能放入实现 Runable Callable 类线程,不能直接放入继承 Thread 的类。
扩充:在 java 中,每次程序运行至少启动 2 个线程。一个是 main 线程,一个是垃圾收集线程。因为每当使用
java 命令执行一个类的时候,实际上都会启动一个 JVM ,每一个 JVM 其实在就是在操作系统中启动了一个进
程。
1.5 匿名内部类方式实现线程的创建
使用线程的内匿名内部类方式,可以方便的实现每个线程执行不同的线程任务操作。
使用匿名内部类的方式实现 Runnable 接口,重新 Runnable 接口中的 run 方法:
public class NoNameInnerClassThread {
public static void main ( String [] args ) {
// new Runnable(){
// public void run(){
// for (int i = 0; i < 20; i++) {
// System.out.println(" 张宇 :"+i);
// }
// }
// }; //‐‐‐ 这个整体 相当于 new MyRunnable()
Runnable r = new Runnable (){
public void run (){
for ( int i = 0 ; i < 20 ; i ++ ) {
System . out . println ( " 张宇 :" + i );
}
}
};
new Thread ( r ). start ();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值