概述
程序:为完成特定任务,用语言编写的一组指令的集合。即一段静态的代码。
进程:是程序的一次执行过程,或者正在运行的一个程序。是一个动态的过程,有它自身的产生、存在和消亡的过程。
线程:进程可进一步细化为线程,是一个程序内部的一条执行路径。
1)若一个进程同一时间并行执行多个线程。就是支持多线程的
2)线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器,线程切换的开销小
3)一个进程中的多个线程共享相同的内存单元|内存地址空间,它们从同一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但是多个线程操作共享的系统资源可能会带来安全隐患。
线程的创建方式
继承Thread类
1、创建一个类继承Thread类
2、重写run()方法 将此线程执行的操作声明在此方法中
3、创建子类对象
4、通过子类对象调用start()方法
// 1、创建一个类继承Thread类
class MyThread extends Thread{
// 2、重写run()方法 将此线程执行的操作声明在此方法中
@Override
public void run() {
for (int i=0;i<100;i++){
if(i%2==0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
public class ThreadTest {
public static void main(String[] args) {
// 3、创建子类对象
MyThread myThread = new MyThread();
// 4、通过子类对象调用start()方法 一启动当前线程 二调用当前线程的run()方法
myThread.start();
}
}
实现Runnable接口
实现多线程的方式二: Runnable接口
- 1、创建一个类实现接口Runnable
- 2、实现类实现接口Runnable的Run()方法
- 3、创建实现类的对象
- 4、将此对象作为参数传递到Thread类的构造器当中,创建Thread类的对象
- 5、通过Thread类的对象调用start()
//1、创建一个类实现接口Runnable
class Mythrwad1 implements Runnable{
//2、实现类实现接口Runnable的Run()方法
@Override
public void run() {
for (int i=0;i<100;i++){
if(i%2==0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
public class ThreadTest02 {
public static void main(String[] args) {
// 3、创建实现类的对象
MyThread myThread = new MyThread();
// 4、将此对象作为参数传递到Thread类的构造器当中,创建Thread类的对象
Thread thread = new Thread(myThread);
// 5、通过Thread类的对象调用start() ①启动线程,对象是谁,线程是谁 ②调用当前线程的run()-->调用Runable类型的 target
thread.start();
实现 Callable 接口
- 1、创建一个实现Callable接口的类
- 2、实现Call()方法,将此线程要操作的内容声明在此
- 3、创建Callable接口实现类的对象
- 4、将Callable接口实现类的对象作为参数传递给FutureTask构造器当中,创建FutureTask对象
- 5、将FutureTask对象传递给Thread构造器,创建Thread类对象并调用start()方法
- 6、得到Callable接口中Call()方法的返回值
//1、创建一个实现Callable接口的类
class Numthread implements Callable<Integer>{
// 2、实现Call()方法,将此线程要操作的内容声明在此
@Override
public Integer call() throws Exception {
int sum=0;
for (int i=1;i<100;i++){
if (i%2==0){
System.out.println(i);
sum+=i;
}
}
return sum;
}
}
public class CallableTest {
public static void main(String[] args) {
//3、创建Callable接口实现类的对象
Numthread n1 = new Numthread();
//4、将Callable接口实现类的对象作为参数传递给FutureTask构造器当中,创建FutureTask对象
FutureTask<Integer> futureTask = new FutureTask<Integer>(n1);
//5、将FutureTask对象传递给Thread构造器,创建Thread类对象并调用start()方法
Thread thread = new Thread(futureTask);
thread.start();
try {
//6、得到Callable接口中Call()方法的返回值
//get()方法返回值即为FutureTask构造器中 Callable接口实现类的Call()方法的返回值
Integer o = futureTask.get();
System.out.println("和为:"+o);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
线程池
背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。
思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建、销毁、实现重复利用。
好处:提高响应速度(减少创建型线程时间)、降低资源消耗(重复利用线程池中的线程。不需要每都创建)、便于线程管理。
步骤:
1、提供指定线程数量的线程池
2、执行指定线程操作,需提供Runnable接口或 Callable 接口的实现类
3、关闭线程池
class Number implements Runnable{
@Override
public void run() {
for (int i=0;i<=100;i++){
if (i%2==0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
public class ThreadPool {
public static void main(String[] args) {
// 1、提供指定线程数量的线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
ThreadPoolExecutor es=(ThreadPoolExecutor) executorService;
// 设置线程池的属性
es.setCorePoolSize(10);
// 2、执行指定线程操作,需提供Runnable接口或 Callable 接口的实现类
executorService.execute(new Number());//适用于Runnable接口
// executorService.submit() 适用于Callable接口
// 3、关闭线程池
executorService.shutdown();
}
}