热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java基础学Java怎么能不了解多线程Lambda表达式

多线程程序,进程,线程1、程序(program):一个固定的运行逻辑和数据的集合,是一个静态

多线程


程序,进程,线程

1、程序(program):一个固定的运行逻辑和数据的集合,是一个静态的概念,一般都存储在磁盘中
2、进程(process):一个正在运行的程序,是一个程序的一次运行,是一个动态的概念,有自己独立的资源分配,是一个独立资源分配单位。资源:cpu 和 内存(ram)
3、线程(thread):一条独立的执行路径,多线程中,在执行某个程序的时候,该程序可以有多个子任务,每个线程都可以独立的完成其中的一个任务,在各个任务之间,没有依赖关系,可以单独运行
4、进程和线程的关系
进程是用于资源分配的单位;
一个进程中,可以有多个线程,并且至少有一条线程;
线程不会独立分配资源,一个进程中所有的线程是共享同一个进程中所有的资源的。


并行和并发

1、并行:多个任务(进程,线程)同时运行,在某个时间点,有多个任务在执行。
条件:多个cpu,多核
2、并发:多个任务(进程,线程)同时发起,但是不能同时执行,(只有一个cpu),只能是同时要求执行。就只能在某个时间片内,将多个任务都有过执行,一个cpu在不同的任务之间进行不断的切换,每个任务时间比较短的,cpu切换速度是比较快的,所有让用户感觉像是多个任务在同时执行。


多线程的第一种实现方式

1、继承一个Thread
2、步骤
(1)定义一个类,让这个类继承Thread
(2)重写Thread类中的run()方法
(3)创建自定义类型的对象
(4)调用线程中的启动方法start();
3、使用匿名内部类实现线程
4、注意
th.run();//如果直接调用run方法,就不再是开启一个线程了,就是普通的调用一下run方法


多线程的第二种实现方式

1、实现Runnable接口:Runnable接口的实现类对象,表示具体的一个任务,将来创建线程对象之后,让线程去执行这个任务
2、步骤
(1) 定义一个类,实现Runnable接口
(2)重写任务类中的run方法
(3)创建一个任务类对象
(4)创建一个Thread类的一个对象,传入任务类对象
(5)调用Thread类中的start方法开启线程
3、使用匿名内部类实现


Thread类中的常用方法

1、获取线程的名称
getName()
注意事项:
(1)如果没有给线程起名,那么线程默认的名称就是Thread-x,x是序号,从0开始
(2)可以使用对象的引用调用getName()方法,也可以在线程类中,调用getName方法
(3)Runnable 的实现类中,是没有getName()方法的
2、设置线程的名称
setName(String name)
注意事项:
(1)使用线程对象的引用,调用该方法就能实现对线程设置名称
(2)线程设置名称,既可以在启动之前,也可以在启动之后,如果是启动之后,那么run方法如果要获取名称,就有可能获取不到设置的名称。
3、构造方法
Thread(String name):给线程通过构造方法起名字
Thread(Runnable targer,String name):在给线程传入任务类对象target的同时,也给线程起名字
4、获取当前的线程对象
currentThread()
注意事项:
(1)返回的就是当前正在执行这段代码的线程对象
(2)那条线程在执行这段代码,返回的就是那条线程
5、线程休眠
Thread.sleep(long time)
注意事项:
(1)有一个中断异常
(2)在普通的方法中,可以进行声明或者捕获
(3)在run方法中,是不能进行异常的声明,只能处理(try 。。catch)
6、守护线程
setDaemon(boolean flag)每条线程默认不是守护线程,只有设定一个flag为true的时候,该线程才变成守护线程
isDaemon():判断每条线程是否是守护线程


线程优先级

1、setPriority(int newPriority) 更改线程的优先级 数字越大,优先级越高,数字越小,优先级越低
数组范围:1 - 10,默认状态5
通过这个方法,设置当前线程的优先级,优先级高的线程能够让cpu多运行一会,优先级低的线程cpu就运行的少
2、getPriority()获取线程的优先级
3、有三个优先级常量
MAX_PRIORITY 10
MIN_PRIORITY 1
NORM_PRIORITY 5


多线程中的线程安全问题

问题的描述
某段代码没有执行完的时候,cpu可能会被其他的线程抢走,结果就导致这段代码在执行的时候会出现一些问题
原因:没有保证某段代码执行的完整性,原子性
希望:这段代码要么全执行,要么全不执行


同步代码块

1、同步代码块:
使用一种格式,达到让某段代码在执行的时候,cpu不会切换到影响当前代码上去
这种格式:可以确保cpu在执行A线程的时候不会切换到影响A线程执行的其他线程上去
2、使用格式
synchronized(锁对象){
需要保证完整性,和一致性的一段代码(需要同步的代码)
}


同步方法

1、如果在方法中,所有的代码都需要加上同步代码块,使用同步方法这种简写的格式,来替代同步代码块
2、格式:
权限修饰符 [ 静态修饰符] synchronized 返回值类型 方法名(参数列表){
需要同步的方法体。
}
3、同步方法的锁对象
如果是非静态的同步方法,同步方法的锁对象就是this,当前对象,那个对象调用this所在的方法,这个同步方法的锁对象就是谁
如果是静态的同步方法,,同步方法的锁对象,就是当前类的字节码对象,类名.class(在方法区中的一个对象),那个类调用这个同步方法,这个同步方法使用的就是那个类的字节码对象

package com.ujiuye.demos;public class Demo_1 {
//多线程中的安全问题public static void main(String[] args) {PrintLogo pl = new PrintLogo();PrintLogo pl1 = new PrintLogo();Thread th1 = new Thread("线程A") {@Overridepublic void run() {while (true) {pl.print_1();}}};Thread th2 = new Thread("线程B") {@Overridepublic void run() {while (true) {pl1.print_2();}}};th1.start();th2.start();}
}class PrintLogo {static Object obj = new Object();String str = "1";//静态的同步方法,锁对象就是该类的字节码对象,类名.classpublic static synchronized void print_1() {System.out.print("中");System.out.print("公");System.out.print("教");System.out.println("育");}public static synchronized void print_2() {System.out.print("优");System.out.print("就");System.out.println("业");}// 普通的同步方法,同步方法的锁对象就是thispublic synchronized void print_1() {System.out.print("中");System.out.print("公");System.out.print("教");System.out.println("育");}public synchronized void print_2() {System.out.print("优");System.out.print("就");System.out.println("业");//同步代码块实现public static void print_1() {synchronized(str){System.out.print("中");System.out.print("公");System.out.print("教");System.out.println("育");}}public void print_2() {synchronized (str) {System.out.print("优");System.out.print("就");System.out.println("业");}}}

线程火车票案例

package com.DaYu;
//三个窗口对应三个线程,同时售卖100张票,打印某某某窗口卖出了一张票,还剩几张票
public class Demo01 {public static void main(String[] args) {Tickets th1 = new Tickets("窗口1");Tickets th2 = new Tickets("窗口2");Tickets th3 = new Tickets("窗口3");th1.start();th2.start();th3.start();}
}class Tickets extends Thread {static int ticket &#61; 100;public Tickets() {super();}public Tickets(String name) {super(name);}&#64;Overridepublic void run() {while(true) {synchronized (Tickets.class) {if(ticket <&#61;0) {break;}else {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}ticket--;System.out.println(getName()&#43;"卖了一张票&#xff0c;还剩"&#43;ticket&#43;"张票");}}} }
}

package com.DaYu;import java.awt.Window;//三个窗口对应三个线程&#xff0c;同时售卖100张票&#xff0c;打印某某某窗口卖出了一张票&#xff0c;还剩几张票
public class Demo02 {public static void main(String[] args) {Windows w &#61; new Windows();Thread th1 &#61; new Thread(w,"窗口1");Thread th2 &#61; new Thread(w,"窗口2");Thread th3 &#61; new Thread(w,"窗口3");th1.start();th2.start();th3.start();}
}class Windows implements Runnable {int num &#61; 100;&#64;Overridepublic void run() {while(true) {synchronized (this) {if(num <&#61; 0) {break;}else {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}num--;System.out.println(Thread.currentThread().getName()&#43;"卖了一张票&#xff0c;还剩"&#43;num&#43;"张票");}}}}}

线程的生命周期

1、别名&#xff1a;线程的状态图&#xff0c;线程的证明周期图&#xff0c;线程的状态周期
2、状态罗列&#xff1a;
新建态:刚创建好线程对象的时候&#xff0c;刚new出来
就绪态&#xff1a;线程准备好了所有的运行资源&#xff0c;就等着cpu来临
运行态&#xff1a;cpu正在执行的线程状态
阻塞态&#xff1a;线程处于休眠&#xff0c;(wait)或者缺少了一些资源&#xff0c;即使cpu来临&#xff0c;也执行不了
死亡态&#xff1a;线程运行完成&#xff0c;线程出现异常&#xff0c;调用方法结束
在这里插入图片描述


Java中关于线程状态的描述

1、java语言中,获取线程的状态的方法
getState():返回的是当前线程对象的状态对象&#xff0c;返回值类型Thread.State,State是Thread的一个内部类
2、Thread.State&#xff1a;java语言中&#xff0c;描述线程状态
由于线程的状态是有限个&#xff0c;所以描述该类的对象&#xff0c;不需要手动的创建&#xff0c;直接就在类型创建好了&#xff0c;直接获取就可以了&#xff0c;这种类型就是枚举类型&#xff0c;每个对象&#xff0c;称为枚举项&#xff0c;Thread.State有六个枚举项&#xff1a;
NEW:新建态&#xff0c;没有开启线程
RUNNABLE&#xff1a;就绪态和运行态
BLOCKED&#xff1a;阻塞态&#xff08;等待锁&#xff0c;I/O&#xff09;
WAITING:阻塞态&#xff08;调用了wait()方法&#xff0c;等待其他线程唤醒的状态&#xff09;
TIMED_WAITING:阻塞态&#xff08;调用了sleep,调用了有时间的wait() 方法&#xff09;
TERMINATED&#xff1a;死亡态


线程池

在没有任务的时候&#xff0c;先把线程对象准备好&#xff0c;存储到一个容器中&#xff0c;一旦有任务需要执行&#xff0c;就不需要去创建对象了&#xff0c;也不需要手动开启线程&#xff0c;而是直接将任务交给获取到的线程池对象去执行
1、步骤&#xff1a;获取线程池的对象&#xff0c;创建任务类对象&#xff0c;将任务类对象提交给线程池中
2、获取一个线程池对象
工具类&#xff1a; Executors&#xff1a;生成线程池的一个工具类&#xff0c;根据需求生成指定大小的线程池对象
ExecutorService Executors.newSingleThreadExecutor()创建一个有单个线程的线程池
ExecutorService Executors.newFixedThreadPool(int nThreads)创建一个可以指定线程数量的线程池
3、创建一个任务类对象
4、将任务类对象提交到线程池中
ExecutorService&#xff1a;是一个接口&#xff0c;不需要手动创建该类的实现类对象&#xff0c;使用方法获取的就是该接口的一个实现类对象
submit(Runnable r):可以将一个任务类对象提交到线程池中&#xff0c;如果有空闲的线程&#xff0c;就可以马上执行这个任务&#xff0c;没有空闲的线程&#xff0c;会让提交的任务进入等待的状态
shutdown():结束线程池&#xff0c;已经提交的保证完成&#xff0c;不准在提交了
shutdownNow();结束线程池&#xff0c;已经开始运行的&#xff0c;保证全部完成&#xff0c;还没有运行的&#xff0c;已经提交&#xff0c;不给运行

package com.ujiuye.demos;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class Demo_6 {
//获取一个有单个线程的线程池public static void main(String[] args) {Task task &#61; new Task();Task_1 ta &#61; new Task_1();Task_2 tt &#61; new Task_2();
// 通过工具类获取具有一个线程的线程池对象ExecutorService es &#61; Executors.newSingleThreadExecutor();es.submit(task);// 获取一个指定线程个数的线程池ExecutorService ex &#61; Executors.newFixedThreadPool(2);ex.submit(task);ex.submit(ta);
// ex.shutdown();//结束线程池&#xff0c;已经提交的&#xff0c;全部完成&#xff0c;不准再提交ex.submit(tt);ex.shutdownNow();}
}

Lambda表达式&#xff08;jdk1.8&#xff09;

1、概述
本质&#xff1a;表示的是一个对象&#xff0c;指定接口的实现类对象
2、前提&#xff1a;
函数式接口&#xff1a;只有一个抽象方法的接口&#xff0c;可以使用&#64;FunctionalInterface 检测接口是否是函数式接口
3、好处:
对匿名内部类的格式简化&#xff0c;大幅提高开发效率
4、格式详解&#xff1a;
格式&#xff1a;
(参数列表) -> {方法体}
说明&#xff1a;
(参数列表) 表示的是实现接口中&#xff0c;抽象方法的参数
-> 箭头运算符&#xff0c;或者称为Lambda运算符&#xff0c;用于分隔前后两部分的
{方法体}
也称为Lambda体&#xff0c;表示重写抽象方法的具体实现&#xff0c;在一些情况中&#xff0c;{}是可以省略的
语法格式1&#xff1a;没有参数&#xff0c;没有返回值&#xff08;接口中的抽象方法&#xff09;
()->System.out.println(“test”);
语法格式2&#xff1a;有一个参数没有返回值
(x)->System.out.println(x*x);
语法格式3&#xff1a;多个参数没有返回值
(x,y)->System.out.println(x &#43; y);
语法格式4&#xff1a;多个参数&#xff0c;有返回值&#xff0c;多条语句

5、特殊情况
&#xff08;1&#xff09;方法体语句只有一句且不能有return&#xff0c;可以省略大括号的
()->一条语句&#xff1b;
(2)有且只有一个参数&#xff0c;可以省略小括号
x-> System.out.println(x * x);
&#xff08;3&#xff09;Lambda体只有一句&#xff0c;且有返回值&#xff0c;return和大括号可以一起省略

{方法体}
也称为Lambda体&#xff0c;表示重写抽象方法的具体实现&#xff0c;在一些情况中&#xff0c;{}是可以省略的
语法格式1&#xff1a;没有参数&#xff0c;没有返回值&#xff08;接口中的抽象方法&#xff09;
()->System.out.println(“test”);
语法格式2&#xff1a;有一个参数没有返回值
(x)->System.out.println(x*x);
语法格式3&#xff1a;多个参数没有返回值
(x,y)->System.out.println(x &#43; y);
语法格式4&#xff1a;多个参数&#xff0c;有返回值&#xff0c;多条语句

5、特殊情况
&#xff08;1&#xff09;方法体语句只有一句且不能有return&#xff0c;可以省略大括号的
()->一条语句&#xff1b;
(2)有且只有一个参数&#xff0c;可以省略小括号
x-> System.out.println(x * x);
&#xff08;3&#xff09;Lambda体只有一句&#xff0c;且有返回值&#xff0c;return和大括号可以一起省略


推荐阅读
author-avatar
杨浩
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有