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

多线程

程序,进程,线程

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") {
			@Override
			public void run() {
				while (true) {
					pl.print_1();
				}
			}
		};

		Thread th2 = new Thread("线程B") {
			@Override
			public void run() {
				while (true) {
					pl1.print_2();
				}
			}
		};
		th1.start();
		th2.start();
	}
}

class PrintLogo {
	static Object obj = new Object();
	String str = "1";

//静态的同步方法,锁对象就是该类的字节码对象,类名.class
	public 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("业");
	}

//	普通的同步方法,同步方法的锁对象就是this
		public 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 = 100;
	  
	   public Tickets() {
		super();
	}

	public Tickets(String name) {
		super(name);
	}

	@Override
	   public void run() {
		   while(true) {
			 synchronized (Tickets.class) {
				 if(ticket <=0) {
				     break;
			     }else {
					 try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
			    	 ticket--;
					  System.out.println(getName()+"卖了一张票,还剩"+ticket+"张票");
				  }
			 }
		   }		   
	    }
}

package com.DaYu;

import java.awt.Window;

//三个窗口对应三个线程,同时售卖100张票,打印某某某窗口卖出了一张票,还剩几张票
public class Demo02 {
	public static void main(String[] args) {
		Windows w = new Windows();
		Thread th1 = new Thread(w,"窗口1");
		Thread th2 = new Thread(w,"窗口2");
		Thread th3 = new Thread(w,"窗口3");
		th1.start();
		th2.start();
		th3.start();
	}
}


class Windows implements Runnable {
	int num = 100;
	
	@Override
	public void run() {
		while(true) {
			synchronized (this) {
				if(num <= 0) {
					break;
				}else {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					num--;
					System.out.println(Thread.currentThread().getName()+"卖了一张票,还剩"+num+"张票");
				}
			}
		}
	}
	 
}

线程的生命周期

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

Java中关于线程状态的描述

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

线程池

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

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 = new Task();
		Task_1 ta = new Task_1();
		Task_2 tt =  new Task_2();
//		通过工具类获取具有一个线程的线程池对象
		ExecutorService es = Executors.newSingleThreadExecutor();
		es.submit(task);
			
//		获取一个指定线程个数的线程池
		ExecutorService ex = Executors.newFixedThreadPool(2);
		ex.submit(task);
		ex.submit(ta);
//		ex.shutdown();//结束线程池,已经提交的,全部完成,不准再提交
		ex.submit(tt);
		ex.shutdownNow();
	}
}

Lambda表达式(jdk1.8)

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

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

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

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

猜你喜欢

转载自blog.csdn.net/qq_41401295/article/details/106556137