首页 > 代码库 > javaSE第二十四天

javaSE第二十四天

第二十四天????363

1:多线程(理解)????363

(1)JDK5以后的Lock????363

A:定义????363

B:方法:????364

C:具体应用(以售票程序为例)????364

1,. SellTicket类????364

2,. SellTicketDemo测试类????365

(2)死锁问题的描述和代码体现????365

1. DieLockDemo测试类????365

2. DieLock类(该类继承自Thread????366

3. MyLock(锁对象类)????367

(3)生产者和消费者多线程体现(线程间通信问题)????367

A:最基本的版本,只有一个数据。????367

1. Student资源类????367

2. SetThread(生产者类)????368

3. GetThread(消费者类)????368

4. StudentDemo测试类????369

B:改进版本,给出了不同的数据,并加入了同步机制????369

1. Student资源类????369

2. SetThread(生产者类)????370

3. GetThread(消费者)????370

4. StudentDemo(测试类)????371

C:等待唤醒机制改进该程序,让数据能够实现依次的出现????372

1. Student(资源类)????372

2. SetThread(生产者类)????373

3. GetThread(消费者类)????374

4. StudentDemo(测试类)????374

D:等待唤醒机制的代码优化。把数据及操作都写在了资源类中????376

1. Student(资源类,把数据及操作都写在资源类中)????376

2. SetThread(生产者类)????377

3. GetThread(消费者类)????378

4. StudentDemo(测试类)????378

(4)线程组????380

1. MyRunnable(线程类)????380

2. ThreadGroupDemo(测试类)????380

(5)线程池????382

1. MyRunnable(线程类)????382

2. ExecutorsDemo(线程池类)????382

(6)多线程实现的第三种方案????383

(7)匿名内部类方法实现多线程????386

(8)定时器的介绍????387

1. TimerDemo类(任务完成之后,可以终止定时器)????387

2. TimerDemo2类(任务完成之后,不终止定时器)????388

3. 案例:定时删除某个目录下的所有文件????389

(9)多线程的面试题????390

2:设计模式(理解)????391

(1)面试对象的常见设计原则????391

(2)设计模式概述和分类????391

(3)改进的设计模式????391

A:简单工厂模式????391

B:工厂方法模式????393

C:单例模式(掌握)????395

a:饿汉式:????395

b:懒汉式:????396

(4)Runtime????398

?

?

?

第二十四天

1:多线程(理解)
????(1)JDK5以后的Lock

????????A:定义

JDK5以后的针对线程的锁定操作和释放操作(Lock是一个接口,具体实例由其实现类ReentrantLock

????????B:方法:

????????????实现类ReenTrantlock的方法:

????????????void lock()加锁

????????????void unlock():解锁

????????C:具体应用(以售票程序为例)

????????????1,. SellTicket

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

?

public?class SellTicket implements Runnable {

?

????// 定义票

????private?int?tickets = 100;

?

????// 定义锁对象

????private Lock lock = new ReentrantLock();

?

????@Override

????public?void run() {

????????while (true) {

????????????try {

????????????????// 加锁

????????????????lock.lock();

????????????????if (tickets > 0) {

????????????????????try {

????????????????????????//为了模拟真实环境,对线程进行了延迟

????????????????????????Thread.sleep(100);

????????????????????} catch (InterruptedException e) {

????????????????????????e.printStackTrace();

????????????????????}

????????????????????System.out.println(Thread.currentThread().getName()

????????????????????????????+ "正在出售第" + (tickets--) + "张票");

????????????????}

????????????} finally {

????????????????// 释放锁

????????????????lock.unlock();

????????????}

????????}

????}

?

}

?

?

????????????2,. SellTicketDemo测试类

/*

* 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,

* 为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

*

* Lock

* ????????void lock(): 获取锁。

* ????????void unlock():释放锁。

* ReentrantLockLock的实现类.

* 通过ReentrantLock类来创建锁对象

*/

public?class SellTicketDemo {

????public?static?void main(String[] args) {

????????// 创建资源对象

????????SellTicket st = new SellTicket();

?

????????// 创建三个窗口

????????Thread t1 = new Thread(st, "窗口1");

????????Thread t2 = new Thread(st, "窗口2");

????????Thread t3 = new Thread(st, "窗口3");

?

????????// 启动线程

????????t1.start();

????????t2.start();

????????t3.start();

????}

}

?

?

????(2)死锁问题的描述和代码体现

????????1. DieLockDemo测试类

/*

* 同步的弊端:

* ????????A:效率低

* ????????B:容易产生死锁

*

* 死锁:

* ????????两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象。

*

* 举例:

* ????????中国人,美国人吃饭案例。

* ????????正常情况:

* ????????????中国人:筷子两支

* ????????????美国人:刀和叉

* ????????现在:

* ????????????中国人:筷子1支,刀一把

* ????????????美国人:筷子1支,叉一把

*/

public?class DieLockDemo {

????public?static?void main(String[] args) {

????????DieLock dl1 = new DieLock(true);

????????DieLock dl2 = new DieLock(false);

?

????????dl1.start();

????????dl2.start();

????}

}

?

?

????????2. DieLock类(该类继承自Thread

/**

* 死锁演示

* @author asus1

*

*/

public?class DieLock extends Thread {

?

????private?boolean?flag;

?

????public DieLock(boolean?flag) {

????????this.flag = flag;

????}

?

????@Override

????public?void run() {

????????if (flag) {

????????????synchronized (MyLock.objA) {

????????????????System.out.println("if objA");

????????????????synchronized (MyLock.objB) {

????????????????????System.out.println("if objB");

????????????????}

????????????}

????????} else {

????????????synchronized (MyLock.objB) {

????????????????System.out.println("else objB");

????????????????synchronized (MyLock.objA) {

????????????????????System.out.println("else objA");

????????????????}

????????????}

????????}

????}

}

?

????????3. MyLock(锁对象类)

/**

* 死锁演示

* @author asus1

*

*/

public?class MyLock {

????// 创建两把锁对象

????public?static?final Object objA = new Object();

????public?static?final Object objB = new Object();

}

?

????(3)生产者和消费者多线程体现(线程间通信问题)

????????以学生作为资源来实现的

????????

????????资源类:Student

????????设置数据类:SetThread(生产者)

????????获取数据类:GetThread(消费者)

????????测试类:StudentDemo

????????

????????代码:

????????????A:最基本的版本,只有一个数据。

????????????????1. Student资源类

/*

* Student:资源类

*/

public?class Student {

????public String name;

????public?int?age;

}

?

????????????????2. SetThread(生产者类)

/*

* 生产者类:

*/

public?class SetThread implements Runnable {

????//保证每个线程是对同一个对象进行操作

????private Student s;

?

????public SetThread(Student s) {

????????this.s = s;

????}

?

????@Override

????public?void run() {

????????// Student s = new Student();

????????s.name = "林青霞";

????????s.age = 27;

????}

}

?

????????????????3. GetThread(消费者类)

/*

* 消费者类

*/

public?class GetThread implements Runnable {

????//保证每个线程是对同一个对象进行操作

????private Student s;

?

????public GetThread(Student s) {

????????this.s = s;

????}

?

????@Override

????public?void run() {

????????// Student s = new Student();

????????System.out.println(s.name + "---" + s.age);

????}

}

?

?

????????????????4. StudentDemo测试类

/*

* 分析:

* ????????资源类:Student????

* ????????设置学生数据:SetThread(生产者)

* ????????获取学生数据:GetThread(消费者)

* ????????测试类:StudentDemo

*

* 问题1:按照思路写代码,发现数据每次都是:null---0

* 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个

* 如何实现呢?

* ????????在外界把这个数据创建出来,通过构造方法传递给其他的类。

*

*/

public?class StudentDemo {

????public?static?void main(String[] args) {

????????//创建资源

????????Student s = new Student();

????????

????????//设置和获取的类

????????SetThread st = new SetThread(s);

????????GetThread gt = new GetThread(s);

?

????????//线程类

????????Thread t1 = new Thread(st);

????????Thread t2 = new Thread(gt);

?

????????//启动线程

????????t1.start();

????????t2.start();

????}

}

?

?

????????????B:改进版本,给出了不同的数据,并加入了同步机制

????????????????1. Student资源类

/*

* 资源类:

*/

public?class Student {

????String name;

????int?age;

}

?

?

????????????????2. SetThread(生产者类)

/*

* 生产者类:

*/

public?class SetThread implements Runnable {

?

????private Student s;

????private?int?x = 0;

?

????public SetThread(Student s) {

????????this.s = s;

????}

?

????@Override

????public?void run() {

????????while (true) {

????????????//加入了同步代码块,要保证多个线程是同意把锁

????????????synchronized (s) {

????????????????if (x % 2 == 0) {

????????????????????s.name = "林青霞";//刚走到这里,就被别人抢到了执行权

????????????????????s.age = 27;

????????????????} else {

????????????????????s.name = "刘意"; //刚走到这里,就被别人抢到了执行权

????????????????????s.age = 30;

????????????????}

????????????????x++;

????????????}

????????}

????}

}

?

?

????????????????3. GetThread(消费者)

/*

* 消费者类:

*/

public?class GetThread implements Runnable {

????private Student s;

?

????public GetThread(Student s) {

????????this.s = s;

????}

?

????@Override

????public?void run() {

????????while (true) {

????????????//加入了同步代码块

????????????synchronized (s) {

????????????????System.out.println(s.name + "---" + s.age);

????????????}

????????}

????}

}

?

?

????????????????4. StudentDemo(测试类)

/*

* 分析:

* ????????资源类:Student????

* ????????设置学生数据:SetThread(生产者)

* ????????获取学生数据:GetThread(消费者)

* ????????测试类:StudentDemo

*

* 问题1:按照思路写代码,发现数据每次都是:null---0

* 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个

* 如何实现呢?

* ????????在外界把这个数据创建出来,通过构造方法传递给其他的类。

*

* 问题2:为了数据的效果好一些,我加入了循环和判断,给出不同的值,这个时候产生了新的问题

* ????????A:同一个数据出现多次

* ????????B:姓名和年龄不匹配

* 原因:

* ????????A:同一个数据出现多次

* ????????????CPU的一点点时间片的执行权,就足够你执行很多次。

* ????????B:姓名和年龄不匹配

* ????????????线程运行的随机性

* 线程安全问题:

* ????????A:是否是多线程环境????????

* ????????B:是否有共享数据????????

* ????????C:是否有多条语句操作共享数据????

* 解决方案:

* ????????加锁。

* ????????注意:

* ????????????A:不同种类的线程都要加锁。

* ????????????B:不同种类的线程加的锁必须是同一把。

*/

public?class StudentDemo {

????public?static?void main(String[] args) {

????????//创建资源

????????Student s = new Student();

????????

????????//设置和获取的类

????????SetThread st = new SetThread(s);

????????GetThread gt = new GetThread(s);

?

????????//线程类

????????Thread t1 = new Thread(st);

????????Thread t2 = new Thread(gt);

?

????????//启动线程

????????t1.start();

????????t2.start();

????}

}

?

?

????????????C:等待唤醒机制改进该程序,让数据能够实现依次的出现

????????????????Object类的方法:

wait():让线程等待,并释放锁

????????????????notify():唤醒线程,并加锁

????????????????notifyAll() (多生产多消费)

????????????????1. Student(资源类)

/*

* 资源类:

*/

public?class Student {

????String name;

????int?age;

????boolean?flag; // 默认情况是没有数据,如果是true,说明有数据

}

?

?

????????????????2. SetThread(生产者类)

/*

* 生产者类:加入了等待-唤醒机制

*/

public?class SetThread implements Runnable {

?

????private Student s;

????private?int?x = 0;

?

????public SetThread(Student s) {

????????this.s = s;

????}

?

????@Override

????public?void run() {

????????while (true) {

????????????synchronized (s) {

????????????????//判断有没有

????????????????if(s.flag){

????????????????????try {

????????????????????????s.wait(); //t1等着,释放锁

????????????????????} catch (InterruptedException e) {

????????????????????????e.printStackTrace();

????????????????????}

????????????????}

????????????????

????????????????if (x % 2 == 0) {

????????????????????s.name = "林青霞";

????????????????????s.age = 27;

????????????????} else {

????????????????????s.name = "刘意";

????????????????????s.age = 30;

????????????????}

????????????????x++; //x=1

????????????????

????????????????//修改标记

????????????????s.flag = true;

????????????????//唤醒线程

????????????????s.notify(); //唤醒t2,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。

????????????}

????????????//t1有,或者t2

????????}

????}

}

?

????????????????3. GetThread(消费者类)

/*

* 消费者类:加入了等待-唤醒机制

*/

public?class GetThread implements Runnable {

????private Student s;

?

????public GetThread(Student s) {

????????this.s = s;

????}

?

????@Override

????public?void run() {

????????while (true) {

????????????synchronized (s) {

????????????????if(!s.flag){

????????????????????try {

????????????????????????s.wait(); //t2就等待了。立即释放锁。将来醒过来的时候,是从这里醒过来的时候

????????????????????} catch (InterruptedException e) {

????????????????????????e.printStackTrace();

????????????????????}

????????????????}

????????????????

????????????????System.out.println(s.name + "---" + s.age);

????????????????//林青霞---27

????????????????//刘意---30

????????????????

????????????????//修改标记

????????????????s.flag = false;

????????????????//唤醒线程

????????????????s.notify(); //唤醒t1

????????????}

????????}

????}

}

?

????????????????4. StudentDemo(测试类)

/*

* 分析:

* ????????资源类:Student????

* ????????设置学生数据:SetThread(生产者)

* ????????获取学生数据:GetThread(消费者)

* ????????测试类:StudentDemo

*

* 问题1:按照思路写代码,发现数据每次都是:null---0

* 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个

* 如何实现呢?

* ????????在外界把这个数据创建出来,通过构造方法传递给其他的类。

*

* 问题2:为了数据的效果好一些,我加入了循环和判断,给出不同的值,这个时候产生了新的问题

* ????????A:同一个数据出现多次

* ????????B:姓名和年龄不匹配

* 原因:

* ????????A:同一个数据出现多次

* ????????????CPU的一点点时间片的执行权,就足够你执行很多次。

* ????????B:姓名和年龄不匹配

* ????????????线程运行的随机性

* 线程安全问题:

* ????????A:是否是多线程环境????????

* ????????B:是否有共享数据????????

* ????????C:是否有多条语句操作共享数据????

* 解决方案:

* ????????加锁。

* ????????注意:

* ????????????A:不同种类的线程都要加锁。

* ????????????B:不同种类的线程加的锁必须是同一把。

*

* 问题3:虽然数据安全了,但是呢,一次一大片不好看,我就想依次的一次一个输出。

* 如何实现呢?

* ????????通过Java提供的等待唤醒机制解决。

*

* 等待唤醒:

* ????????Object类中提供了三个方法:

* ????????????wait():等待

* ????????????notify():唤醒单个线程

* ????????????notifyAll():唤醒所有线程

* ????????为什么这些方法不定义在Thread类中呢?

* ????????????这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象。

* ????????????所以,这些方法必须定义在Object类中。

*/

public?class StudentDemo {

????public?static?void main(String[] args) {

????????//创建资源

????????Student s = new Student();

????????

????????//设置和获取的类

????????SetThread st = new SetThread(s);

????????GetThread gt = new GetThread(s);

?

????????//线程类

????????Thread t1 = new Thread(st);

????????Thread t2 = new Thread(gt);

?

????????//启动线程

????????t1.start();

????????t2.start();

????}

}

?

?

?

?

????????????D:等待唤醒机制的代码优化。把数据及操作都写在了资源类中

????????????1. Student(资源类,把数据及操作都写在资源类中)

/*

* 资源类:把数据及操作都写在资源类上面

*/

public?class Student {

????private String name;

????private?int?age;

????private?boolean?flag; // 默认情况是没有数据,如果是true,说明有数据

?

????//使用同步方法解决线程安全问题

????public?synchronized?void set(String name, int?age) {

????????// 如果有数据,就等待

????????if (this.flag) {

????????????try {

????????????????this.wait();

????????????} catch (InterruptedException e) {

????????????????e.printStackTrace();

????????????}

????????}

?

????????// 设置数据

????????this.name = name;

????????this.age = age;

?

????????// 修改标记

????????this.flag = true;

????????this.notify();

????}

?

????//使用同步方法解决线程安全问题

????public?synchronized?void get() {

????????// 如果没有数据,就等待

????????if (!this.flag) {

????????????try {

????????????????this.wait();

????????????} catch (InterruptedException e) {

????????????????e.printStackTrace();

????????????}

????????}

?

????????// 获取数据

????????System.out.println(this.name + "---" + this.age);

?

????????// 修改标记

????????this.flag = false;

????????this.notify();

????}

}

?

?

????????????2. SetThread(生产者类)

/*

* 生产者类:

*/

public?class SetThread implements Runnable {

?

????private Student s;

????private?int?x = 0;

?

????public SetThread(Student s) {

????????this.s = s;

????}

?

????@Override

????public?void run() {

????????while (true) {

????????????if (x % 2 == 0) {

????????????????s.set("林青霞", 27);

????????????} else {

????????????????s.set("刘意", 30);

????????????}

????????????x++;

????????}

????}

}

?

?

????????????3. GetThread(消费者类)

/*

* 消费者类:

*/

public?class GetThread implements Runnable {

????private Student s;

?

????public GetThread(Student s) {

????????this.s = s;

????}

?

????@Override

????public?void run() {

????????while (true) {

????????????s.get();

????????}

????}

}

?

?

????????????4. StudentDemo(测试类)

?

/*

* 分析:

* ????????资源类:Student????

* ????????设置学生数据:SetThread(生产者)

* ????????获取学生数据:GetThread(消费者)

* ????????测试类:StudentDemo

*

* 问题1:按照思路写代码,发现数据每次都是:null---0

* 原因:我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个

* 如何实现呢?

* ????????在外界把这个数据创建出来,通过构造方法传递给其他的类。

*

* 问题2:为了数据的效果好一些,我加入了循环和判断,给出不同的值,这个时候产生了新的问题

* ????????A:同一个数据出现多次

* ????????B:姓名和年龄不匹配

* 原因:

* ????????A:同一个数据出现多次

* ????????????CPU的一点点时间片的执行权,就足够你执行很多次。

* ????????B:姓名和年龄不匹配

* ????????????线程运行的随机性

* 线程安全问题:

* ????????A:是否是多线程环境????????

* ????????B:是否有共享数据????????

* ????????C:是否有多条语句操作共享数据????

* 解决方案:

* ????????加锁。

* ????????注意:

* ????????????A:不同种类的线程都要加锁。

* ????????????B:不同种类的线程加的锁必须是同一把。

*

* 问题3:虽然数据安全了,但是呢,一次一大片不好看,我就想依次的一次一个输出。

* 如何实现呢?

* ????????通过Java提供的等待唤醒机制解决。

*

* 等待唤醒:

* ????????Object类中提供了三个方法:

* ????????????wait():等待

* ????????????notify():唤醒单个线程

* ????????????notifyAll():唤醒所有线程

* ????????为什么这些方法不定义在Thread类中呢?

* ????????????这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象。

* ????????????所以,这些方法必须定义在Object类中。

*

* 最终版代码中:

* ????????Student的成员变量给私有的了。

* ????????把设置和获取的操作给封装成了功能,并加了同步。

* ????????设置或者获取的线程里面只需要调用方法即可。

*/

public?class StudentDemo {

????public?static?void main(String[] args) {

????????//创建资源

????????Student s = new Student();

????????

????????//设置和获取的类

????????SetThread st = new SetThread(s);

????????GetThread gt = new GetThread(s);

?

????????//线程类

????????Thread t1 = new Thread(st);

????????Thread t2 = new Thread(gt);

?

????????//启动线程

????????t1.start();

????????t2.start();

????}

}

?

?

?

?

?

????(4)线程组

????????具体案例介绍

????????????1. MyRunnable(线程类)

/*

* 实现Runnable接口的线程类

*/

public?class MyRunnable implements Runnable {

?

????@Override

????public?void run() {

????????for (int?x = 0; x < 100; x++) {

????????????//打印当前线程的名称及数字

????????????System.out.println(Thread.currentThread().getName() + ":" + x);

????????}

????}

?

}

?

????????????2. ThreadGroupDemo(测试类)

/*

* 线程组: 把多个线程组合到一起。

* 它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。

*

* 线程组类:ThreadGroup

* ????????构造方法:public ThreadGroup(String name):构造一个带名称的线程组

* ????????普通方法:public final String getName():返回此线程组的名称。

* ????注意:默认情况下,所有的线程都属于同一个组,就是main

* Thread类:

* ????????构造方法:

* ????????public Thread(ThreadGroup group,

Runnable target,

String name):创建一个属于某个线程组的且带名称的线程

普通方法

public final ThreadGroup getThreadGroup():返回该线程所属的线程组

?

*/

public?class ThreadGroupDemo {

????public?static?void main(String[] args) {

????????// method1();

?

????????// 我们如何修改线程所在的组呢?

????????// 创建一个线程组

????????// 创建其他线程的时候,把其他线程的组指定为我们自己新建线程组

????????method2();

?

????????// t1.start();

????????// t2.start();

????}

?

????private?static?void method2() {

????????// ThreadGroup(String name)

????????ThreadGroup tg = new ThreadGroup("这是一个新的组");

?

????????MyRunnable my = new MyRunnable();

????????// Thread(ThreadGroup group, Runnable target, String name)

????????Thread t1 = new Thread(tg, my, "林青霞");

????????Thread t2 = new Thread(tg, my, "刘意");

????????

????????System.out.println(t1.getThreadGroup().getName());

????????System.out.println(t2.getThreadGroup().getName());

????????

????????//通过组名称设置后台线程,表示该组的线程都是后台线程

????????tg.setDaemon(true);

????}

?

????private?static?void?method1() {

????????MyRunnable my = new MyRunnable();

????????Thread t1 = new Thread(my, "林青霞");

????????Thread t2 = new Thread(my, "刘意");

????????// 我不知道他们属于那个线程组,我想知道,怎么办

????????// 线程类里面的方法:public final ThreadGroup getThreadGroup()

????????ThreadGroup tg1 = t1.getThreadGroup();

????????ThreadGroup tg2 = t2.getThreadGroup();

????????// 线程组里面的方法:public final String getName()

????????String name1 = tg1.getName();

????????String name2 = tg2.getName();

????????System.out.println(name1);

????????System.out.println(name2);

????????// 通过结果我们知道了:线程默认情况下属于main线程组

????????// 通过下面的测试,你应该能够看到,默任情况下,所有的线程都属于同一个组

????????System.out.println(Thread.currentThread().getThreadGroup().getName());

????}

}

?

?

?

????(5)线程池

????????案例代码体现:

????????1. MyRunnable(线程类)

/*

* 实现Runnable接口的线程类

*/

public?class MyRunnable implements Runnable {

?

????@Override

????public?void run() {

????????for (int?x = 0; x < 100; x++) {

????????????//打印当前线程的名称及数字

????????????System.out.println(Thread.currentThread().getName() + ":" + x);

????????}

????}

?

}

?

????????2. ExecutorsDemo(线程池类)

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

?

/*

* 线程池的好处:线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。

*

* 如何实现线程的代码呢?

* ????????A:创建一个线程池对象,控制要创建几个线程对象。

* ????????????public static ExecutorService newFixedThreadPool(int nThreads)

* ????????B:这种线程池的线程可以执行:

* ????????????可以执行Runnable对象或者Callable对象代表的线程

* ????????????做一个类实现Runnable接口。

* ????????C:调用如下方法即可

* ????????????Future<?> submit(Runnable task)

*????????????<T> Future<T> submit(Callable<T> task)

*????????D:我就要结束,可以吗?

*????????????可以。

*/

public?class ExecutorsDemo {

????public?static?void main(String[] args) {

????????// 创建一个线程池对象,控制要创建几个线程对象。

????????// public static ExecutorService newFixedThreadPool(int nThreads)

????????ExecutorService pool = Executors.newFixedThreadPool(2);

?

????????// 可以执行Runnable对象或者Callable对象代表的线程

????????pool.submit(new MyRunnable());

????????pool.submit(new MyRunnable());

?

????????//结束线程池

????????pool.shutdown();

????}

}

?

?

????(6)多线程实现的第三种方案

????????多线程实现第三种方式介绍

????????1. MyCallable

import java.util.concurrent.Callable;

?

//Callable:是带泛型的接口。

//这里指定的泛型其实是call()方法的返回值类型。

public?class MyCallable implements?Callable {

?

????@Override

????public Object call() throws Exception {

????????for (int?x = 0; x < 100; x++) {

????????????System.out.println(Thread.currentThread().getName() + ":" + x);

????????}

????????return?null;

????}

?

}

?

????????2. CallableDemo

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

?

/*

* 多线程实现的方式3

* ????A:创建一个线程池对象,控制要创建几个线程对象。

* ????????????public static ExecutorService newFixedThreadPool(int nThreads)

* ????????B:这种线程池的线程可以执行:

* ????????????可以执行Runnable对象或者Callable对象代表的线程

* ????????????做一个类实现Runnable接口。

* ????????C:调用如下方法即可

* ????????????Future<?> submit(Runnable task)

*????????????<T> Future<T> submit(Callable<T> task)

*????????D:我就要结束,可以吗?

*????????????可以。

*/

public?class CallableDemo {

????public?static?void main(String[] args) {

????????//创建线程池对象

????????ExecutorService pool = Executors.newFixedThreadPool(2);

????????

????????//可以执行Runnable对象或者Callable对象代表的线程

????????pool.submit(new MyCallable());

????????pool.submit(new MyCallable());

????????

????????//结束

????????pool.shutdown();

????}

}

?

????????多线程案例:求和

????????1. MyCallable

import java.util.concurrent.Callable;

?

/*

* 线程求和案例

*/

public?class MyCallable implements Callable<Integer> {

?

????private?int?number;

?

????public MyCallable(int?number) {

????????this.number = number;

????}

?

????@Override

????public Integer call() throws Exception {

????????int?sum = 0;

????????for (int?x = 1; x <= number; x++) {

????????????sum += x;

????????}

????????return?sum;

????}

?

}

?

????????2. CallableDemo

import java.util.concurrent.ExecutionException;

import java.util.concurrent.ExecutorService;

import?java.util.concurrent.Executors;

import java.util.concurrent.Future;

?

/*

* 多线程实现的方式3

* ????A:创建一个线程池对象,控制要创建几个线程对象。

* ????????????public static ExecutorService newFixedThreadPool(int nThreads)

* ????????B:这种线程池的线程可以执行:

* ????????????可以执行Runnable对象或者Callable对象代表的线程

* ????????????做一个类实现Runnable接口。

* ????????C:调用如下方法即可

* ????????????Future<?> submit(Runnable task)

*????????????<T> Future<T> submit(Callable<T> task)

*????????D:我就要结束,可以吗?

*????????????可以。

*/

public?class CallableDemo {

????public?static?void main(String[] args) throws InterruptedException, ExecutionException {

????????// 创建线程池对象

????????ExecutorService pool = Executors.newFixedThreadPool(2);

?

????????// 可以执行Runnable对象或者Callable对象代表的线程

????????Future<Integer> f1 = pool.submit(new MyCallable(100));

????????Future<Integer> f2 = pool.submit(new MyCallable(200));

?

????????// V get()

????????Integer i1 = f1.get();

????????Integer i2 = f2.get();

?

????????System.out.println(i1);

????????System.out.println(i2);

?

????????// 结束

????????pool.shutdown();

????}

}

?

?

????(7)匿名内部类方法实现多线程

????

/*

* 匿名内部类的格式:

* ????????new 类名或者接口名() {

* ????????????重写方法;

* ????????};

* ????????本质:是该类或者接口的子类对象。

*/

public?class ThreadDemo {

????public?static?void main(String[] args) {

????????// 继承Thread类来实现多线程

????????new Thread() {

????????????public?void run() {

????????????????for (int?x = 0; x < 100; x++) {

????????????????????System.out.println(Thread.currentThread().getName() + ":"

????????????????????????????+ x);

????????????????}

????????????}

????????}.start();

?

????????// 实现Runnable接口来实现多线程

????????new Thread(new Runnable() {

????????????@Override

????????????public?void run() {

????????????????for (int?x = 0; x < 100; x++) {

????????????????????System.out.println(Thread.currentThread().getName() + ":"

????????????????????????????+ x);

????????????????}

????????????}

????????}) {

????????}.start();

?

????????// 更有难度的,以下的这个代码是不会报错的,可以正常运行,需要能看懂

????????new Thread(new Runnable() {

????????????@Override

????????????public?void run() {

????????????????for (int?x = 0; x < 100; x++) {

????????????????????System.out.println("hello" + ":" + x);

????????????????}

????????????}

????????}) {

????????????public?void run() {

????????????????for (int?x = 0; x < 100; x++) {

????????????????????System.out.println("world" + ":" + x);

????????????????}

????????????}

????????}.start();

????}

}

?

????(8)定时器的介绍

????????1. TimerDemo类(任务完成之后,可以终止定时器)

import java.util.Timer;

import java.util.TimerTask;

?

/*

* 定时器:可以让我们在指定的时间做某件事情,还可以重复的做某件事情。

* 依赖TimerTimerTask这两个类:

* Timer:定时

* ????????public Timer()

* ????????public void schedule(TimerTask task,long delay)

* ????????????????????????????:安排在指定延迟后执行指定的任务。

* ????????public void schedule(TimerTask task, Date time)

* ????????????????????????????:安排在指定的时间执行指定的任务

?

* ????????public void schedule(TimerTask task,long delay,long period)

* ???????????????????????? :安排指定的任务在指定的时间开始进行重复的固定延迟执行。

* ????????public void cancel():终止此计时器,丢弃所有当前已安排的任务。

* ???????????????????????????? 这不会干扰当前正在执行的任务(如果存在)。

* TimerTask:任务类

* ????????????子类继承该方法,并重写里面的run()方法

*/

public?class TimerDemo {

????public?static?void main(String[] args) {

????????// 创建定时器对象

????????Timer t = new Timer();

????????// 3秒后执行爆炸任务

????????// t.schedule(new MyTask(), 3000);

????????//结束任务

????????t.schedule(new MyTask(t), 3000);

????}

}

?

// 做一个任务

class MyTask extends TimerTask {

?

????private Timer t;

????

????public MyTask(){}

????

????public MyTask(Timer t){

????????this.t = t;

????}

????//要做的任务

????@Override

????public?void run() {

????????System.out.println("beng,爆炸了");

????????//任务执行完成之后,终止此定时器

????????t.cancel();

????}

}

?

????????2. TimerDemo2类(任务完成之后,不终止定时器)

import java.util.Timer;

import java.util.TimerTask;

?

/*

* 定时器:可以让我们在指定的时间做某件事情,还可以重复的做某件事情。

* 依赖TimerTimerTask这两个类:

* Timer:定时

* ????????public Timer()

* ????????public void schedule(TimerTask task,long delay)

* ????????public void schedule(TimerTask task,long delay,long period)

* ????????public void cancel()

* TimerTask:任务

*/

public?class TimerDemo2 {

????public?static?void main(String[] args) {

????????// 创建定时器对象

????????Timer t = new Timer();

????????// 3秒后执行爆炸任务第一次,如果不成功,每隔2秒再继续炸

????????t.schedule(new MyTask2(), 3000, 2000);

????????//该程序不会自动停止

????}

}

?

// 做一个任务

class MyTask2 extends TimerTask {

????@Override

????public?void run() {

????????System.out.println("beng,爆炸了");

????}

}

?

????????3. 案例:定时删除某个目录下的所有文件

import java.io.File;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Timer;

import java.util.TimerTask;

?

/*

* 需求:在指定的时间删除我们的指定目录(你可以指定c盘,但是我不建议,我使用项目路径下的demo)

*/

?

class DeleteFolder extends TimerTask {

?

????//定时任务

????@Override

????public?void run() {

????????File srcFolder = new File("demo");

????????deleteFolder(srcFolder);

????}

?

????// 递归删除目录

????public?void deleteFolder(File srcFolder) {

????????//获取源目录下的所有File对象的数组

????????File[] fileArray = srcFolder.listFiles();

????????

????????//判断该File数组是否为null

????????if (fileArray != null) {

????????????//不为null,循环遍历 该数组

????????????for (File file : fileArray) {

????????????????

????????????????//判断该file对象是否为目录

????????????????if (file.isDirectory()) {

????????????????????//如果为目录,则进行递归

????????????????????deleteFolder(file);

????????????????} else {

????????????????????//不为目录,则打印被删除文件的名称并同时删除文件

????????????????????System.out.println(file.getName() + ":" + file.delete());

????????????????}

????????????}

????????????//如果File数组为null,则打印被删除文件的名称并同时删除文件

????????????System.out.println(srcFolder.getName() + ":" + srcFolder.delete());

????????}

????}

}

?

//测试类

public?class TimerTest {

????public?static?void main(String[] args) throws ParseException {

????????//创建定时器对象

????????Timer t = new Timer();

?

????????String s = "2014-11-27 15:45:00";

????????SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

????????Date d = sdf.parse(s);

????????//在指定的时间,删除某个目录下的所有文件

????????t.schedule(new DeleteFolder(), d);

????}

}

?

?

????(9)多线程的面试题

1:多线程有几种实现方案,分别是哪几种?

????两种。

????

????继承Thread

????实现Runnable接口

????

????扩展一种:实现Callable接口。这个得和线程池结合。

?

2:同步有几种方式,分别是什么?

????两种。

????

????同步代码块

????同步方法

?

3:启动一个线程是run()还是start()?它们的区别?

????start();

????

????run():封装了被线程执行的代码,直接调用仅仅是普通方法的调用

????start():启动线程,并由JVM自动调用run()方法

?

4:sleep()和wait()方法的区别

????sleep():必须指时间;不释放锁。

????wait():可以不指定时间,也可以指定时间;释放锁。

?

5:为什么wait(),notify(),notifyAll()等方法都定义在Object类中

????因为这些方法的调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。

????而Object代表任意的对象,所以,定义在这里面。

?

6:线程的生命周期图

????新建 -- 就绪 -- 运行 -- 死亡

????新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡

????建议:画图解释。

?

?

2:设计模式(理解)
????(1)面试对象的常见设计原则

????????单一

????????开闭

????????里氏

????????依赖注入

????????接口

????????迪米特

????(2)设计模式概述和分类

????????A:经验的总结

????????B:三类

????????????创建型

????????????结构型

????????????行为型

????(3)改进的设计模式

????????A:简单工厂模式

????????????1. Animal类(顶层抽象类)

/*

* 动物类:抽象类

*/

public?abstract?class Animal {

????//吃的方法

????public?abstract?void eat();

}

?

????????????2. Cat

/*

* 猫类:继承动物类

*/

public?class Cat extends Animal {

????@Override

????public?void eat() {

????????System.out.println("猫吃鱼");

????}

?

}

?

????????????3. Dog

/*

* 狗类:继承动物类

*/

public?class Dog extends Animal {

?

????@Override

????public?void eat() {

????????System.out.println("狗吃肉");

????}

}

?

????????????4. AnimalFactory类(动物工厂类)

????????????

/*

* 动物工厂类:专门造动物的

*/

public?class AnimalFactory {

????//构造方法私有,不允许创建对象

????private AnimalFactory() {

????}

????//根据传递过来的类型,创建指定的对象,可通过类名直接调用

????public?static Animal createAnimal(String type) {

????????if ("dog".equals(type)) {

????????????return?new Dog();

????????} else?if ("cat".equals(type)) {

????????????return?new?Cat();

????????} else {

????????????return?null;

????????}

????}

}

?

????????????5. AnimalDemo(测试类)

/*

* 测试类

*/

public?class AnimalDemo {

????public?static?void main(String[] args) {

????????// 具体类调用

????????Dog d = new Dog();

????????d.eat();

????????Cat c = new Cat();

????????c.eat();

????????System.out.println("------------");

?

????????// 工厂改进后

????????Animal a = AnimalFactory.createAnimal("dog");

????????a.eat();

????????a = AnimalFactory.createAnimal("cat");

????????a.eat();

?

????????// NullPointerException,在使用对象之前,应该先对对象是否为null进行判断

????????a = AnimalFactory.createAnimal("pig");

????????if (a != null) {

????????????a.eat();

????????} else {

????????????System.out.println("对不起,暂时不提供这种动物");

????????}

????}

}

?

????????????

????????B:工厂方法模式

????????????1. Animal(动物类)

/*

* 动物类:抽象 类

*/

public?abstract?class Animal {

????public?abstract?void eat();

}

?

????????????2. Cat类(猫类)

/*

* 猫类:继承自动物类

*/

public?class Cat extends Animal {

?

????@Override

????public?void eat() {

????????System.out.println("猫吃鱼");

????}

?

}

?

????????????3. Dog(狗类)

/*

* 狗类:继承自动物类

*/

public?class Dog extends Animal {

?

????@Override

????public?void eat() {

????????System.out.println("狗吃肉");

????}

?

}

?

????????????4. Factory(接口)

/*

* Factory:工厂接口

*/

public?interface Factory {

????//定义了创建动物的方法

????public?abstract Animal createAnimal();

}

?

????????????5. CatFactory(猫工厂)

/*

* CatFactory:猫工厂,实现工厂接口,专门用来生成猫

*/

public?class CatFactory implements Factory {

?

????@Override

????public Animal createAnimal() {

????????return?new Cat();

????}

?

}

?

????????????6. DogFactory(狗工厂)

/*

* 狗工厂:实现了工厂接口,专门用来造狗

*/

public?class DogFactory implements Factory {

?

????@Override

????public Animal createAnimal() {

????????return?new Dog();

????}

?

}

?

????????????7. AnimalDemo测试类

/*

* 测试类

*/

public?class AnimalDemo {

????public?static?void main(String[] args) {

????????// 需求:我要买只狗

????????Factory f = new DogFactory();

????????Animal a = f.createAnimal();

????????a.eat();

????????System.out.println("-------");

????????

????????//需求:我要买只猫

????????f = new CatFactory();

????????//使用特定的工厂专门造狗,造猫

????????a = f.createAnimal();

????????a.eat();

????}

}

?

????????C:单例模式(掌握)

????????????a:饿汉式:

????????????说明:饿汉式:提前造好一个对象(开发中常用,因为不容易出现问题)

????????????1.

/*

* 单例模式:饿汉式:提前造好一个对象

*/

public?class Student {

????// 构造私有

????private Student() {

????}

?

????// 自己造一个

????// 静态方法只能访问静态成员变量,加静态

????// 为了不让外界直接访问修改这个值,加private

????private?static Student s = new Student();

?

????// 提供公共的访问方式

????// 为了保证外界能够直接使用该方法,加静态

????public?static Student getStudent() {

????????return?s;

????}

}

?

?

????????????2. StudentDemo测试类

/*

* 单例模式:保证类在内存中只有一个对象。

*

* 如何保证类在内存中只有一个对象呢?

* ????????A:把构造方法私有

* ????????B:在成员位置自己创建一个对象

* ????????C:通过一个公共的方法提供访问

*/

public?class StudentDemo {

????public?static?void main(String[] args) {

????????//通过单例模式得到对象

????????Student s1 = Student.getStudent();

????????Student s2 = Student.getStudent();

????????System.out.println(s1 == s2);

?

????????System.out.println(s1); // nullcn.itcast_03.Student@175078b

????????System.out.println(s2);// nullcn.itcast_03.Student@175078b

????}

}

?

?

????????????b:懒汉式:

????????????说明:需要用的时候,才去创建对象。(面试常面)

????????????1. Teacher

/*

* 单例模式:

* ????????饿汉式:类一加载就创建对象

* ????????懒汉式:用的时候,才去创建对象

*

* 面试题:单例模式的思想是什么?请写一个代码体现。

*

* ????????开发:饿汉式(是不会出问题的单例模式)

* ????????面试:懒汉式(可能会出问题的单例模式)

* ????????????A:懒加载(延迟加载)????

* ????????????B:线程安全问题

* ????????????????a:是否多线程环境????

* ????????????????b:是否有共享数据????

* ????????????????c:是否有多条语句操作共享数据 ????

*/

public?class Teacher {

????//构造方法私有化

????private Teacher() {

????}

?

????//定义一个对象

????private?static Teacher t = null;

?

????//加入同步关键字解决线程安全问题

????public?synchronized?static Teacher getTeacher() {

????????// t1,t2,t3

????????//如果对象为null,就创建,否则不创建

????????if (t == null) {

????????????//t1,t2,t3

????????????t = new Teacher();

????????}

????????return?t;

????}

}

?

?

????????????2. TeacherDemo

/*

* 测试类

*/

public?class TeacherDemo {

????public?static?void main(String[] args) {

????????Teacher t1 = Teacher.getTeacher();

????????Teacher t2 = Teacher.getTeacher();

????????System.out.println(t1 == t2);

????????System.out.println(t1); // cn.itcast_03.Teacher@175078b

????????System.out.println(t2);// cn.itcast_03.Teacher@175078b

????}

}

?

?

?

????(4)Runtime

????????JDK提供的一个单例模式应用的类。

????????还可以调用dos命令。

????????

import java.io.IOException;

?

/*

* Runtime:每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。

* exec(String command)

*/

public?class RuntimeDemo {

????public?static?void main(String[] args) throws IOException {

????????Runtime r = Runtime.getRuntime();

//????????r.exec("winmine");

????????//打开记事本

????????// r.exec("notepad");

????????//打开计算器

????????// r.exec("calc");

????????//关机(时间是以秒计算的)

//????????r.exec("shutdown -s -t 10000");

????????//取消shutdown的命令

????????r.exec("shutdown -a");

????}

}

?

/*Runtime类使用了单例模式

* class Runtime {

* ????????private Runtime() {}

* ????????private static Runtime currentRuntime = new Runtime();

* ????????public static Runtime getRuntime() {

* ????return currentRuntime;

* ????}

* }

*/

?

?

javaSE第二十四天