线程创建与使用

来源:互联网 发布: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 99
main 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即可。缺点是不能继承其他类


原创粉丝点击