电子政务网站课程设计,我的网站模板,医院网站 行风建设,关键词优化seo公司#x1f451;专栏内容#xff1a;Java⛪个人主页#xff1a;子夜的星的主页#x1f495;座右铭#xff1a;前路未远#xff0c;步履不停 目录 一、线程与进程二、创建线程方法1、继承Thread类2、实现Runnable接口3、两者区别4、举个栗子5、简洁写法Ⅰ、Thread匿名内部类写… 专栏内容Java⛪个人主页子夜的星的主页座右铭前路未远步履不停 目录 一、线程与进程二、创建线程方法1、继承Thread类2、实现Runnable接口3、两者区别4、举个栗子5、简洁写法Ⅰ、Thread匿名内部类写法Ⅱ、Runnable匿名内部类写法Ⅲ、使用Lambda表达式 嗨想象一下你的面前有一张展开的白纸而你的左手和右手各握一支画笔。你的任务是在同一时间左手画出一个方形右手画出一个圆形。你觉得这能够完成吗我相信大多数人会认为这是不可能完成的任务。因为我们的大脑是单线程的一次只能专注于一项任务一心二用在绝大多数情况下是不可行的。然而计算机不同它具备多线程编程的能力可以同时处理多个任务。现在让我们一起探索Java中多线程这个神奇的功能吧。
一、线程与进程
进程是计算机中执行中的程序的实例。它是操作系统进行管理和调度的基本单位。
线程有时被称为轻量级进程是程序中的一个单独的执行流。它是操作系统调度的最小单位。与进程相比线程之间的上下文切换通常更为迅速和高效。一个线程就是一个 “执行流”。每个线程之间都可以按照顺讯执行自己的代码、多个线程之间 “同时” 执行着多份代码。
进程是操作系统能独立调度的最小单位而线程是进程中可并发执行的单元一个应用程序至少包括1个进程而1个进程包括1个或多个线程每个进程在执行过程中拥有独立的内存单元而一个进程的多个线程在执行过程中共享内存。 那我们来简单的类比一下吧 计算机的CPU就像一个工厂而进程就是工厂里面的车间线程就是车间里面的工人。
我们能够发现多核CPU对应多个工厂这些工厂可以从事不同的生产任务。比如有炼铁的、炼油的、食品加工等等。在一个工厂中又可以包含一个或多个车间进程但是由于电力资源有限同一时间就只能有一个车间在运行。换句话说对于单核CPU同一时间只能处理一个进程其他进程处在等待状态。而一个车间中可以有一个或多个工人线程协同工作他们共享内部资源共同完成任务。 同一个进程中这些线程共用同一份资源内存 硬盘…但是每个线程独立去CPU上调度状态、上下文、优先级、记账信息…各自有各自的一份 所以进程是操作系统进行分配的基本单位。而线程是操作系统进行调度执行的基本单位。 【面试题】谈谈进程和线程的区别和联系 进程是包含线程的都是实现并发编程的方式但是线程比进程更轻量。 进程是系统分配资源的基本单位线程是系统调度的基本单位。创建进程的时候把分配资源虚拟地址空间、文件描述符表的工作给做了后面创建线程直接共用资源即可。 进程有独立的地址空间彼此之间不会相互影响到进程的独立性。多个线程共用这份地址空间一个线程一旦抛出异常就可能会导致进程异常结束。 进程和进程之间不共享内存空间同一个进程的线程之间共享同一个内存空间。 二、创建线程方法
在 Java 中有两种创建多线程的方式分别是继承 Thread 类和实现 Runnable 接口。下面让我们一起来学习下这两种创建多线程的方法吧。
1、继承Thread类
class Mythread extends Thread{public void run() {System.out.println(这是线程运行代码!);}
}public class Main {public static void main(String[] args) {Mythread mythread new Mythread();mythread.start();}
}创建一个类继承 Thread 重写run方法该方法包含线程的实际执行逻辑。
start()方法start() 方法是Thread类的一个方法它用于启动线程并调用线程的run()方法。 在这个例子中myThread.start() 会启动一个新的线程并在新线程中执行 run() 方法中定义的代码。
如果把myThread.start();改成myThread.run();后运行的结果也是hello world。这两个有什么不一样呢
run只是上面的入口方法并没有调用系统api也没有创建真正的线程来。 2、实现Runnable接口
class Myrunnable implements Runnable{public void run() {System.out.println(这是线程运行代码!);}
}public class Main {public static void main(String[] args) {Thread thread new Thread(new Myrunnable());thread.start();}
}该方法主要是创建一个类实现 Runnable 接口重写run方法。
3、两者区别
Thread这里是直接把要完成的工作放到了Thread的Run方法中
Runnable这里则是分开了把要完成的工作放到了Runnable中再让Runnable和Thread配合。 把线程要执行的任务和线程本身进一步解耦合了。并发编程中来完成某个工作使用Runnable描述这个工作的具体细节。这样使用多线程的方式就可以使用Runnable来搭配线程使用。使用线程池的方式就可以使用Runnable来搭配线程池使用使用协议的方式也可以使用Runnable搭配协程。 特征继承 Thread 类实现 Runnable 接口类的继承关系直接继承 Thread 类。类实现 Runnable 接口可以继承其他类。创建方式创建类的子类重写 run() 方法。创建类实现 Runnable 接口实现 run() 方法。多线程对象创建直接创建线程对象的实例。先创建 Runnable 对象再通过 Runnable 对象创建 Thread 对象。启动线程直接调用 start() 方法。调用 Thread 类的构造方法传递 Runnable 对象然后调用 start() 方法。资源共享较难实现资源共享。更容易实现资源共享因为可以共享同一个 Runnable 对象。多态使用难以使用多态因为已经继承了 Thread 类。更容易使用多态因为类可以继续实现其他接口或继承其他类。
4、举个栗子
回到上面的问题。把myThread.start();改成myThread.run();后运行的结果也是hello world。 这两个有什么不一样呢我们来举个栗子看看吧。 class MyThread extends Thread{Overridepublic void run() {while(true){System.out.println(hello thread);}}
}
public class Demo1 {public static void main(String[] args) {MyThread myThread new MyThread();myThread.start();//myThread.run();while(true){System.out.println(hello main);}}
}使用myThread.start();运行的程序会同时打印hello thread 和 hello main 两个循环都在执行两个线程分别执行自己的循环并发性的执行。 而使用myThread.run();运行的程序只会打印hello main 只执行了一个循环。 5、简洁写法
我们可以通过匿名内部类来Thread和Runnable这两种写法。 什么是匿名内部类 匿名内部类是一种在声明和创建类的对象同时进行的特殊形式它没有显式的类名称。这种方式通常用于在使用类的地方定义类的实例尤其是在创建接口的实现或继承抽象类的实例时。 Ⅰ、Thread匿名内部类写法 public static void main(String[] args) {Thread thread new Thread(){Overridepublic void run() {System.out.println(这是线程运行代码!);}};thread.start();}Ⅱ、Runnable匿名内部类写法 public static void main(String[] args) {Thread thread new Thread(new Runnable() {Overridepublic void run() {System.out.println(这是线程运行代码!);}});thread.start();}Ⅲ、使用Lambda表达式
Lambda表达式主要用于实现函数式接口Lambda表达式本质上就是一个匿名函数像这样的匿名函数可以做回调函数来使用。 匿名函数就是没有命名的函数。它具有传递函数体的能力却无需提前声明整个函数的结构。
回调函数则是在程序执行中不需要程序员主动调用的函数。相反它会在特定的时机或条件下由系统或其他代码自动触发执行。程序员通过将函数传递给其他代码实现了一种回调机制使得在适当的时候这个函数会被调用完成特定的操作。
好了废话不多说先用Lambda表达式写一下吧。 public static void main(String[] args) {Thread thread new Thread(() - {System.out.println(这是线程运行代码!);});thread.start();}Thread thread new Thread(() - { 这里使用Lambda表达式创建了一个新的Thread对象构造方法接受一个Runnable接口的实现作为参数。Lambda表达式的内容在大括号中用于定义线程运行时执行的代码块。 线程的创建并不是只有这五种写法还可以用线程池和Callable写法。这个我们后面再聊