day22
一、线程的常用的方法
1.方法:
public final void stop() 强迫线程停止执行
public static void yield() 暂停当前正在执行的线程对象,并执行其他线程(礼让)
public final void join() 等待该线程终止(方法必须在线程开启之后进行调用)
1.1 stop方法
定义类:
package com.lt.demo13;
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
if(i==6){
stop();
}
System.out.println(i);
}
}
}
测试类:
package com.lt.demo13;
public class Test01 {
public static void main(String[] args) {
//实例化线程对象
MyThread m = new MyThread();
m.start();
}
}
1.2 yield方法
测试类:
package com.lt.demo14;
/**
*礼让这个方法在线程开启的前面
*/
public class Test01 {
public static void main(String[] args) {
//实例化线程对象
MyThread m = new MyThread();
//礼让: 注意这个方法在本机上面需要自己敲名字
m.yield();
m.start();
MyThread m1= new MyThread();
m1.start();
}
}
定义类:
package com.lt.demo14;
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName());
}
}
}
1.3 join方法
测试类:
package com.lt.demo15;
/**
* 这个方法是在线程开启之后
*/
public class Test01 {
public static void main(String[] args) throws InterruptedException {
//实例化线程对象
MyThread m1 = new MyThread();
m1.start();
//这个方法有异常,可以进行抛出
m1.join();
MyThread m2 = new MyThread();
m2.start();
}
}
定义类:
package com.lt.demo15;
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+"\t"+i);
}
}
}
二、Object提供操作线程的方法
1.public final void wait() 无限等待(需要被唤醒)
2.public final void wait(long timeout) 计时等待
3.public final void notify() 唤醒在此对象监视器上等待的单个线程(一个)
4.public final void notifyAll() 唤醒在此对象监视器上等待的所有线程(多个)
案例:
测试:
package com.lt.demo16;
public class Test01 {
public static void main(String[] args) {
//定义一个锁对象
Object obj = new Object();
//实例化吃包子的线程
new Thread() {
@Override
public void run() {
//使用对象锁
synchronized (obj) {
System.out.println("我需要一个包子");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("包子好吃");
}
}.start();
//实例化做包子的线程
new Thread() {
@Override
public void run() {
//使用对象锁
synchronized (obj) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("做好了包子");
//唤醒吃包子的人
obj.notify();
}
}
}.start();
}
}
三、线程的消费者和生产者模式
需求:
包子类:
package com.lt.demo17;
/**
* 这些属性需要给其他使用,设计成公共的
*/
public class BaoZi {
public String pi;
public String xian;
//定义一个标记来记录状态false表示没有包子,true表示有包子
public boolean flag = false;
public BaoZi(){
}
}
消费者:
package com.lt.demo17;
public class XiaoFeiZhe extends Thread {
private BaoZi baoZi;
public XiaoFeiZhe(BaoZi baoZi){
this.baoZi=baoZi;
}
@Override
public void run() {
//使用无限循环
while (true){
//锁对象
synchronized (baoZi){
System.out.println("我要吃包子");
if (!baoZi.flag){
try {
baoZi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
System.out.println("我吃"+baoZi.pi+baoZi.xian+"的包子");
//吃完了,把属性全部null
baoZi.pi=null;
baoZi.xian=null;
//标记设计为
baoZi.flag =false;
//唤醒生产者生产包子
baoZi.notify();
}
}
}
}
}
生产者:
package com.lt.demo17;
public class ShengChanZhe extends Thread {
//属性,把BaoZi提出来为属性
private BaoZi baoZi;
//构造方法
public ShengChanZhe(BaoZi baoZi){
this.baoZi=baoZi;
}
@Override
public void run() {
while (true){
synchronized (baoZi){
//判断是否有包子,没有则是无限等待
if (baoZi.flag){
try {
baoZi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
System.out.println("生产包子");
baoZi.pi="面皮";
baoZi.xian="猪肉";
System.out.println("生产l"+baoZi.pi+baoZi.xian+"的包子");
//有包子了,把标记设计成true
baoZi.flag=true;
//通知消费者 唤醒消费者
baoZi.notify();
}
}
}
}
}
测试类:
package com.lt.demo17;
public class Test01 {
public static void main(String[] args) {
//实例化包子对象
BaoZi z= new BaoZi();
//实例化生产者对象
ShengChanZhe s = new ShengChanZhe(z);
s.start();
//实例化消费者对象
XiaoFeiZhe x = new XiaoFeiZhe(z);
x.start();
}
}
四、线程的第三种创建方法
1.定义一个接口类:CallAble
2.重写call方法
3.实例化任务对象 FutureTask 构建一个CallAble的实现类
4.实例化一个线程对象 Thread 构建一个任务对象
5.开启线程
6.调用任务对象的get()方法,可以得到返回值
测试类:
package com.lt.demo18;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//实例化MyCallAble对象
MyCallAble myCallAble = new MyCallAble();
//实例化任务对象
FutureTask<Integer> f = new FutureTask<Integer>(myCallAble);
//实例化Thread线程对象
Thread t = new Thread(f);
t.start();
//调用任务对象的方法get方法 有异常,抛出
Integer i = f.get();
System.out.println(i);
}
}
定义类-MyCallAble类:
package com.lt.demo18;
import java.util.concurrent.Callable;
public class MyCallAble implements Callable<Integer> {
private Integer sum =0;
@Override
public Integer call() throws Exception {
for (int i = 0; i <=100; i++) {
sum+=i;
}
return sum;
}
}
五、枚举
1.概念:就是用来表示一些固定的值,可以使用枚举项来进行表示
2.语法:
访问修饰符 enum 枚举类的名字{
枚举项
}
3.例子:
public enum Color{
RED,BLUE,YELLOW
}
4.特点:
A.每一个枚举类都是enum 的子类
B.每一个枚举项就是一个对象
C.枚举类可以有成员变量
D.枚举类中只能有私有的构造方法 默认就是私有的构造方法
E.枚举类中可以有抽象方法,但是每一个枚举项 都必须重写这个抽象的方法
F.枚举项可以通过枚举类的类名来进行调用
G.枚举项必须写在第一行,不同的使用逗号分开
5.枚举的一些方法:
A.public static <T extends Enum> T valueOf(ClassenumType, String name)
返回带指定名称的指定枚举类型的枚举常量
B.public final String name()
返回此枚举常量的名称
C.public final int compareTo(E o)
比较此枚举与指定对象的顺序
D.public final int ordinal()
返回枚举常量的序数(索引是从0开始)
E.values()
获取所有的枚举项
F.public String toString()
返回枚举常量的名称
六、线程的生命周期
1.线程有6种生命周期,这些生命周期是使用枚举来进行表示
2.获取线程状态:
Thread.State
线程生命周期图:
七、线程池
1.线程池:用来维护线程的程序
2.步骤:
A.通过线程池的工具类来创建线程对象
B.创建一个线程任务对象
C. .将任务对象提交线程池中
D.通过get() 获取到线程执行完的结果
3.创造线程池的对象的方法
A.public static ExecutorServicenewSingleThreadExecutor()
创建线程池(只有一个线程)
B.public static ExecutorServicenewFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池(设置线程的个数)
4.将任务对象提交线程池的方法:
A.Future submit(Callable task)
提交一个返回值的任务用于执行
B.Future<?> submit(Runnable task)
提交一个 Runnable 任务用于执行
八、单例设置
1.单例设置说明:有且仅有一个实例化对象
2.使用场景:加载配置信息 工具类 spring 容器对象的注入
3.有且仅有一个实例化对象
a.私有属性
b.私有的构造方法
c.公有的方法
4.单例设置模式的分类:饿汉 懒汉 双重锁 内部类 枚举(作业).....
8.1 饿汉模式
优点:没有锁机制 效率较高
缺点:项目启动的时候就创建对象,项目会出现卡顿
8.2 懒汉模式
1.懒汉模式
懒加载 谁用谁加载
2.优点:
项目启动的时候 不可能出现卡顿现象
3.缺点:
没有锁的机制 多线程是不安全
8.3 双重锁模式
优点: 在多线程线层安全的
缺点: 效率会降低
定义类:
package com.lt.demo10;
import java.util.Date;
public class DataUtile {
private static DataUtile dataUtile;
public DataUtile(){
}
public static synchronized DataUtile getInstance(){
if (dataUtile==null){
synchronized (DataUtile.class){
if (dataUtile==null){
dataUtile = new DataUtile();
}
}
}
return dataUtile;
}
}
测试类:
package com.lt.demo10;
/**
* 双重锁
*/
public class Test01 {
public static void main(String[] args) {
System.out.println(DataUtile.getInstance());
System.out.println(DataUtile.getInstance());
System.out.println(DataUtile.getInstance());
System.out.println(DataUtile.getInstance());
}
}
测试类:
package com.lt.demo11;
/**
* 查看是否为同一个对象
* 查看地址值是否一样
*/
public class Test01 {
public static void main(String[] args) {
System.out.println(DataUtile.getInstance());
System.out.println(DataUtile.getInstance());
System.out.println(DataUtile.getInstance());
}
}
定义类:
package com.lt.demo11;
public class DataUtile {
public DataUtile(){
}
//定义一个内部类
static class ShowInfo{
static final DataUtile dtaUtile = new DataUtile();
}
//使用一个方法来进行返回值
public static DataUtile getInstance(){
return ShowInfo.dtaUtile;
}
}
九、定时器
1.开发中定时器使用场景:定时发邮件 定时提交日志
2.使用步骤:
A.定义一个类 继承TimerTask
B.创建定时对象 Timer
C.把任务提交到定时器里
3.方法:
a.public void schedule(TimerTask task, longdelay)
安排在指定延迟后执行指定的任务
b.public void schedule(TimerTask task, DatefirstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定延迟执行
c.public void schedule(TimerTask task, Datetime)
安排在指定的时间执行指定的任务
定义类:
package com.lt.demo12;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask {
@Override
public void run() {
System.out.println("你觉得你又行了");
}
}
测试类:
package com.lt.demo12;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import java.util.Timer;
public class Test01 {
public static void main(String[] args) throws ParseException {
//实例化任务对象
MyTimerTask m = new MyTimerTask();
//实例化定时器
Timer t = new Timer();
// t.schedule(m,1000);
//指定时间打印
Scanner input = new Scanner(System.in);
System.out.println("输入一个时间:");
String str = input.nextLine();
SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sp.parse(str);
t.schedule(m,date,2000);
}
}