线程的使用与创建详解

并发:在一段时间内完成任务的量{并发量}
并行:在同一时刻能完成任务的量【并行量】
高并发:上千 万 十万 百万 千万
进程:正在运行的程序 没有先后顺序执行是随机的 线程中cpu时间片分配是随机的
线程: 存在于进程中用来真正执行任务的(计算机运行最小单元)
在线程中CPU的时间片分配是随机的,也就导致了线程的执行是随机的
Java中只有Thread才是线程类,其他的都不是

创建线程:

java有一个专用的线程类Thread【唯一的线程类】
创建方式一: 一个类继承线程类 Thread
重写. run();方法【此线程运行的方法体】
通过 new Thread来创建方法
Thread thread = Thread.currentThread(); // 获取到当前线程对象
System.out.println(thread.getName()); // 获取当前线程的名字

创建线程的方式一 :

类 extends Thread 重写run()方法

  • 应用领域 : 批量产生线程
  • 缺陷 : 单继承缺陷(只能继承一个类,以后扩展不方便)
package demo1;
/**
 * Java中有一个专用的线程类 : Thread 【唯一的线程类】
 * 创建线程的方式一 :  类 extends  Thread
 * 	重写run()方法
 * 应用领域 : 批量产生线程
 * 缺陷 : 单继承缺陷(只能继承一个类,以后扩展不方便)
 */
public class MyThread extends Thread {  // MyThread 线程的子类

	@Override
	public void run() {   // 此线程运行的方法体
		for(;;) {
			System.out.print(getName()+":"); // 获取当前线程的名字
			System.out.print("欢");
			System.out.print("迎");
			System.out.print("光");
			System.out.println("临");
		}
	}
	
}

主函数是主线程,
、Thread.currentThread(); // 获取到当前线程对象
.getName(); // 获取当前线程的名字
Thread.currentThread().getName(); // 获取到当前线程对象的线程名字
.start(); // 启动线程【只有线程才能启动】
.run(); // 普通面向对象的方法调用,并没有开辟一个真实的线程

通过new Thread来创建线程对象

package demo1;

public class Test {
	public static void main(String[] args) { // 主函数(主线程)
//		Thread thread = Thread.currentThread();  // 获取到当前线程对象
//		System.out.println(thread.getName());  // 获取当前线程的名字
		
		for (int i = 1; i <=10; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
		
		// 通过Thread来创建线程对象
		MyThread thread = new MyThread();
		thread.start();  // 启动线程【只有线程才能启动】
//		thread.run();  // 普通面向对象的方法调用,并没有开辟一个真实的线程
		
		for (;;) {
			System.out.println("AAAAA");
		}
		
	}
}

通过Thread使用匿名内部类来创建出线程对象

语法:
Thread XXX = new Thread(){
重写run方法代码块{
}
};
XXX.start(); // 线程启动

package demo1;

public class Test2 {
	public static void main(String[] args) {
		// 通过Thread使用匿名内部类来创建出线程对象
		Thread t1= new Thread() {
			@Override
			public void run() {
				for (int i =1; i<=1000;i++) {
					System.out.println(Thread.currentThread().getName()+": 划船不靠浆"+i);
				}
			}
		};
		t1.start();  // 线程启动
		
		Thread t2= new Thread() {
			@Override
			public void run() {
				for (int i =1; i<=2000;i++) {
					System.out.println(Thread.currentThread().getName()+": 全靠浪"+i);
				}
			}
		};
		// 在线程中CPU的时间片分配是随机的,也就导致了线程的执行是随机的
		t2.start();  // 线程启动
	
	}
}	

线程创建的第二种方式 :

## 类 implements Runnable

*** 重写run()方法**
*** 优点 : 解决了Thread单继承的缺陷问题,但是使用上变麻烦了一点
Runnable 中只有一个run()
public void run() {
}**
run()特点 : 没有返回值,不能抛出异常
引发思考 : 若线程执行后有返回值怎么处理? 使用线程的第三种创建方式来解决此问题

package demo2;
/**
 * 线程创建的第二种方式 : 类  implements Runnable
 *  重写run()方法
 *  优点 : 解决了Thread单继承的缺陷问题,但是使用上变麻烦了一点
 */
public class MyRunnable  implements Runnable{

	@Override
	public void run() {
		for (;;) {
			System.out.println(Thread.currentThread().getName()+":将进酒,杯莫停");
		}
	}
	
	/**
	 * Runnable 中只有一个run()
	 *		 public void run() {
	 *		 }
	 *     run()特点 : 没有返回值,不能抛出异常
	 *   引发思考 : 若线程执行后有返回值怎么处理?   使用线程的第三种创建方式来解决此问题
	 */

}

创建一个Runnable接口类型的对象

Runnable target = new MyRunnable(); // 只是线程运行的一个规范(执行的内容)

package demo2;

public class Test {
	public static void main(String[] args) {
		// 创建一个Runnable接口类型的对象
		Runnable target = new MyRunnable();  // 只是线程运行的一个规范(执行的内容)
		// Java中只有Thread才是线程类,其他的都不是
//		Thread t1 = new Thread(, "测试线程");
//		t1.setName("测试线程");
//		t1.start();  // 启动一个线程
		
		// 阻塞  : 程序是按照一定的顺序执行
		// 非阻塞:各自的程序都是独立运行的
		
		
		for (;;) {
			System.out.println(Thread.currentThread().getName()+":AAAAAAAA");
		}
	}
}

创建的方式

**

## 主流 :采用匿名内部类形式来创建Runnable对象 企业使用的方式 lambda

**

package demo2;

public class Test2 {
	public static void main(String[] args) {
		new Thread(() -> {      // 企业使用的方式  lambda
			for(;;) {
				System.out.println(Thread.currentThread().getName()+":CCCCC");
			}
		}, "小明").start();
	}

	private static void demo3() {
		// 主流 :采用匿名内部类形式来创建Runnable对象
		Thread thread = new Thread(() -> {      // 企业使用的方式  lambda
			for(;;) {
				System.out.println(Thread.currentThread().getName()+":CCCCC");
			}
		}); 
		thread.setName("小张");
		thread.start();
	}

	private static void demo2() {
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				for(;;) {
					System.out.println(Thread.currentThread().getName()+":BBBBB");
				}
			}
		});
		thread.start();
	}

	private static void demo1() {
		//1. 采用匿名内部类形式来创建Runnable接口对象
		Runnable target = new Runnable() {
			@Override
			public void run() {
				for(;;) {
					System.out.println(Thread.currentThread().getName()+":AAAAAA");
				}
			}
		};
		Thread thread = new  Thread(target);
		thread.start();
	}
}

线程创建的第三种方式 :

处理线程执行后有结果返回的场景
语法 : 类 implements Callable
为什么 Callable 是一个泛型接口,泛型就是将来线程执行之后的返回结果类型

package demo3;

import java.util.concurrent.Callable;

/**
 * 线程创建的第三种方式 : 处理线程执行后有结果返回的场景
 * 		语法 :  类  implements  Callable<V>  
 * 		为什么 Callable<V>  是一个泛型接口,泛型就是将来线程执行之后的返回结果类型
 *
 */
public class MyCallable implements Callable<String>{

	@Override
	public String call() throws Exception {  // 线程执行的核心方法,和run作用类似
		StringBuilder builder = new StringBuilder();
		for (int j = 0;j < 100;j++) {
			for (char i = 'a'; i <= 'z'; i++) {
				builder.append(i);
			}
			for (char i = 'A'; i <= 'Z'; i++) {
				builder.append(i);
			}
		}
		return builder.toString();
	}

}

用法:

// 创建Callable接口类型的对象

Callable (范型)callable = new MyCallable();
// 创建一个FutureTask来接收callable执行的任务(只是用来接收线程执行后的结果的)
FutureTask futureTask = new FutureTask(callable);
// 通过查看源码知道 : FutureTask是Runnable的子类
// 能否通过Thread来创建出这个线程呢?
Thread thread = new Thread(futureTask);
thread.start(); // 启动线程
// 要从FutureTask中来接收线程执行的结果**

package demo3;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Test {
	public static void main(String[] args) {
		// 创建Callable接口类型的对象
		Callable<String> callable = new MyCallable();
		// 创建一个FutureTask来接收callable执行的任务(只是用来接收线程执行后的结果的)
		FutureTask<String> futureTask = new FutureTask<String>(callable);
		// 通过查看源码知道 : FutureTask是Runnable的子类
		// 能否通过Thread来创建出这个线程呢?
		Thread thread = new Thread(futureTask);
		thread.start();  // 启动线程
		// 要从FutureTask中来接收线程执行的结果
		try {
			String result = futureTask.get();  // 一直等待线程执行结果的出现
			System.out.println("结果长度:"+result.length());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		
		for (int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
			
		}
	}
}

**

使用lambda表达式来创建callable对象

**

面试 :
run(),start() 有什么区别?
答 : run() 对象的一个普通方法,start()启动一个线程

Runnable与Callable的区别?
Runnable接口中只有run(),它没有返回值, 不能抛出异常
Callable<T>泛型接口只有call(). 有执行的返回值,能抛出异常**
package demo3;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Test2 {
	public static void main(String[] args) {
		// 使用lambda表达式来创建callable对象
		Callable<Integer> callable = () -> {
			int sum = 0;
			for (int i = 1; i <100; i+=2) {
				sum += i*i;
			}
			return sum;
		};
		FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);
		new Thread(futureTask).start();
		try {
			Integer result = futureTask.get();
			System.out.println(result);
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 面试 : 
	   run(),start() 有什么区别?
	     	答 : run() 对象的一个普通方法,start()启动一个线程
	 
	   Runnable与Callable的区别?
			 Runnable接口中只有run(),它没有返回值, 不能抛出异常
			 Callable<T>泛型接口只有call(). 有执行的返回值,能抛出异常
	 */
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值