线程创建与使用
来源:互联网 发布:java 知识库系统 开源 编辑:程序博客网 时间:2024/05/22 07:00
一、概念
每一个程序运行时,内部可能包含多个顺序执行流,每个顺序执行流就是一个线程。
1.线程与进程
进程是运行中的程序,是具有独立功能的,进程是系统进行资源分配的和调度的一个独立单位。
进程的三个特点:
独立性:进程是系统中独立存在的实体,拥有自己独立的资源,每一个进程都有自己的私有地址空间。
动态性:进程与程序的区别是,程序是一个静态的指令集合,而进程是一个在系统中动态活动的指令集合,有生存周期与不同的状态。
并发性:可以在处理器上并发执行,多个进程间不会相互影响。
线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父进程,线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不拥有系统资源,它与此父进程的其他线程共享该线程所拥有的全部资源
二、线程的创建和启动
1.继承Thread类
步骤:a.定义Thread子类,并重写该类的run()方法,该方法就是线程需要完成的任务;
b.创建Thread的实例,就创建了线程对象;
c.调用线程的start()方法就启动了线程。
package Thread;//继承Thread类创建线程public class FirstThread extends Thread {//重写run()方法;使用getName()可以直接返回线程的名字private int i;public void run() {for(i=0;i<100;i++) {System.out.println(getName()+" "+i);}}public static void main(String[] args) throws InterruptedException {for(int i = 0;i<100;i++) {//使用currentThread()方法调用当前线程System.out.println(currentThread().getName()+" "+i);if(i==50) {Thread.sleep(1000);FirstThread th = new FirstThread();th.start();FirstThread th1 = new FirstThread();th1.start();}}}}
运行结果如下(部分):
Thread-0 98
Thread-0 99main 96
main 97
main 98
main 99
Thread-1 47
Thread-1 48
该线程共有三个线程:一个main主线程,两个创建的线程;
currentThread()方法是Thread的静态方法,用于返回当前正在执行的线程对象;getName()返回线程的名字;
注意:继承Thread线程类的方法类创建线程时,多线程间时无法共享实例变量的,如上:i为Thred1的实例变量,不是局部变量。
2.实现Runnable接口创建线程
步骤:a.定义Runnable接口的实现类,重写run()方法,此方法也是线程的执行体(是由Thread将其包装为线程执行体的)
b.创建Runnable接口的实例,以此实例作为Thread的target来创建对象,此对象才是真正的线程对象
package Thread;//事项Runnable接口创建线程public class RunnableThread implements Runnable {//重写其run()方法private int i;@Overridepublic void run() {for(;i<100;i++) {//由于实现Runnable接口,获取当前对象只能用ThreadRunnable().getName();System.out.println(Thread.currentThread().getName()+" "+i);}}public static void main(String[] args) {for(int i=0;i<100;i++) {System.out.println(Thread.currentThread().getName()+" "+i);if(i==10) {//通过new Thread(target,name)创建线程;RunnableThread rt = new RunnableThread();new Thread(rt,"线程1").start();new Thread(rt,"线程2").start();}}}}
运行结果(部分):
线程1 11
线程1 12
main 18
线程1 13
main 19
main 20
使用Thread与Runnable创建线程的区别:
继承Thread类的子类可代表线程的对象,而实现Runnable接口只能作为线程对象的target;
Runnable接口创建的线程可以共享实例变量,Thread不可以。
3.实现Callable接口与Future创建线程
步骤:a.创建Callable接口,实现call()方法,以call()方法作为线程的执行体,该call()方法具有返回值;
b.使用FutureTask类来包装Callable对象,并且封装了其call方法的返回值,
c.使用FutureTask对象作为Thread对象的target创建并启动线程,
d.调用FutureTask对象的get() 方法获得子线程的执行结束后的返回值。
package Thread;import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;public class CallableThread {public static void main(String[] args) {//创建Callable对象CallableThread ca = new CallableThread();//使用Lambda表达式创建Callable<Integer>对象;//使用FutureTask包装Callable对象FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)()->{int i=0;for(;i<100;i++) {System.out.println(Thread.currentThread().getName()+"的循环变量I的值"+i);}return i;});for(int i =0;i<100;i++) {System.out.println(Thread.currentThread().getName()+"的循环变量i的值"+i);if(i==20) {new Thread(task,"有返回值的线程").start();}}try {System.out.println("子线程的返回值:"+task.get());}catch(Exception e) {e.printStackTrace();}}}运行结果(部分):main的循环变量i的值49
有返回值的线程的循环变量I的值25
main的循环变量i的值50
有返回值的线程的循环变量I的值26
main的循环变量i的值51
有返回值的线程的循环变量I的值27
有返回值的线程的循环变量I的值28
子线程的返回值:100
总结:使用lambda表达式创建Callable对象,就无需先创建Callable实现类,再创建对象了,call()方法允许抛出异常和带返回值。
三种方式创建现成的比较:
继承Thread类与实现Runable、Callable接口都可以创建多线程,使用Runable与Callable接口创建基本方式相同,只是用Callable接口实现有返回值,并且抛出异常。
实现接口与继承Thread的优缺点:实现接口还可以继承其他类;使用接口多个线程可以共享一个target对象,使用与多个线程处理一份资源的情况;缺点是要访问当前
线程就要用Thread.currentThread()方法。
使用Thread的优缺点:编写简单,方法当前线程简单直接用this即可。缺点是不能继承其他类
- 线程创建与使用
- 线程的创建与使用
- 线程的创建与使用
- Java中线程池创建与使用
- 线程池的创建与使用
- 使用HandlerThread创建线程并与UI线程通讯
- 线程创建与用法
- 线程创建与退出
- 认识与创建线程
- 线程创建与控制
- 线程创建与等待
- Linux下通用线程池的创建与使用[ZT]
- Linux下通用线程池的创建与使用
- Linux下通用线程池的创建与使用
- Linux下通用线程池的创建与使用(C++)
- Linux下通用线程池的创建与使用
- Linux下通用线程池的创建与使用
- 【转载】Linux下通用线程池的创建与使用
- 一个小项目带你了解rest framework
- R-次要刻度线 参考线 图例
- vue.js
- iOS app开发第三方库
- Random ThreadLocalRandom 产生随机数
- 线程创建与使用
- 编辑器之 sublime 常用快捷键
- 网站该不该加WWW
- ajax规范化格式
- 【笔记】蓝牙BLE开发记录
- 遇到第二个页面需要第一个页面Get解析的json串的数据时所遇到的问题解决方法!!
- robotframework + python 环境自搭建
- LeetCode 27. Remove Element
- 熄灯问题