线程创建与使用

一、概念

每一个程序运行时,内部可能包含多个顺序执行流,每个顺序执行流就是一个线程。

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;
	@Override
	public 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即可。缺点是不能继承其他类


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值