线程相关知识总结

线程是指一个进程内部的子任务,是任务的具体执行的逻辑。并且一个进程至少有一个线程(这个唯一的线程是主线程)

注:进程启动时创建的堆区(Heap)和云空间(MetSpace)是同一个进程内的多个线程共享的

       每个线程都有自己的线程:PC、虚拟机栈、本地方法栈。

JVM必有得五大线程:

  1. 主线程
  2. 清除reference线程
  3. 调用对象finalize方法的线程
  4. 分发处理给JVM信号的线程
  5. 添加事件监听器

创建线程的方式:

Thread  t   =  new  Thread();

注:这句代码是创建线程的最根本的方式,其中传入的参数可以是一个:String类型的线程名字,Runnable类型的实现类;也可以是两个都传。

根据传入的参数可以将创建方式分为:

方式一、继承Thread类

Thread  t  =  new Thread(){ }

t这个线程被调用时会自动调用重写的run()方法。

//自已创建的线程1
Thread t1 = new Thread() {
    //在这里面写线程内部要进行的操作
	@Override
	public void run() {
		System.out.println(i);
		}
	};

方式二:实现Runnable接口

Thread  t  =  new  Thread(new  Runnable( ){  })

注:若采用自己定义A类的实现Runnable接口,在使用这个线程时,-->

在主线程中:首先创建A类对象(创建出来后并不是创建出了线程)

然后通过  Thread  t  =  new  Thread( a )        -->这个过程才是真正创建线程的步骤。

eg:

public class EmailSend extends TasK implements Runnable{
	@Override
	public void run() {
		//获取当前的线程
		Thread currentThread = Thread.currentThread();
		//获取当前线程的名字
		String name = currentThread.getName();
		
		//具体操作
		System.out.println(name + "发送邮件");
	}
	
	
}

public static void main(String[] args) {
		
		//创建自己写的这个类的对象后,并没有创建一个新的线程
		EmailSend emailSend = new EmailSend();
		//通过这种方式才代表创建了一个新的线程
		Thread t1 = new Thread(emailSend, "线程1");
		Thread t2 = new Thread(emailSend, "线程2");
		Thread t3 = new Thread(emailSend, "线程3");
		
		t1.start();
		t2.start();
		t3.start();
	}

方式三:实现Callable接口

(此方式创建能够获得任务具体实现获得的返回结果)

同样,若自己定义A类实现这个接口,也是在内部写具体的任务逻辑,而在使用时要注意:

在main中,创建A类对像后( A  a  =  new  A() ),由于Thread类中的构造函数中,只能传入Runnable类型的,所以要用一个中间类进行转换,将Callable类型转成Runnable,以便能够放入Thread创建线程。

而这个中间类就是   FutureTask<T>  f  =  new  Future<T>( a );

原因:FutureTask是RunnableFuture的实现类,RunnableFuture又继承自Runnable,所以FutureTask间接继承自Runnable,所以能够传入到具体的线程创建操作中。

eg:

MyCallableImpl myCallableImpl1 = new MyCallableImpl(1, 100);
MyCallableImpl myCallableImpl2 = new MyCallableImpl(101, 200);
MyCallableImpl myCallableImpl3 = new MyCallableImpl(201, 300);
		
由于Thread对象中不能传入Callable类型,
所以要通过中间类FutureTask进行转换,,而FutureTask是RunnableFuture的实现类,
RunnableFuture又继承自Runnable,所以FutureTask间接继承自Runnable类,所以能够传入到Thread中
FutureTask<Integer> futureTask1 = new FutureTask<Integer>(myCallableImpl1);
FutureTask<Integer> futureTask2 = new FutureTask<Integer>(myCallableImpl2);
		
Thread t1 = new Thread(futureTask1,"线程1");
Thread t2 = new Thread(futureTask2,"线程2");

class MyCallableImpl implements Callable<Integer>{
	
	private int begin,end;
	
	public MyCallableImpl(int begin,int end){
		this.begin = begin;
		this.end = end;
	}

	@Override
	public Integer call() throws Exception {
		System.out.println(Thread.currentThread().getName() + "线程的call被调用了");
		int sum = 0;
		for(int i = begin;i<=end;i++) {
			sum = sum +i;
		}
		
		return sum;
	}
	
}

方式四:创建线程池:

//利用线程池:
//1、创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
//2、提交Callable接口封装的具体实现
Future<Integer> f1 = executorService.submit(myCallableImpl1);
Future<Integer> f2 = executorService.submit(myCallableImpl2);
Future<Integer> f3 = executorService.submit(myCallableImpl3);
//3、分别获取各线程计算的结果
Integer i1 = f1.get();
Integer i2 = f2.get();
Integer i3 = f3.get();
//4、汇总结果
int ret = i1 + i2 + i3;
System.out.println(ret);
//5、关闭线程池
executorService.shutdownNow();

上面的案例中,创建的是固定大小的线程池,且最多只能有三个线程。若有一个线程需要执行,系统会将任务提交给线程池。将线程池中的空闲线程分配给他;若没有空闲线程,就会进入等待状态。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值