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():释放锁。

* ReentrantLock是Lock的实现类.

* 通过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;

?

/*

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

* 依赖Timer和TimerTask这两个类:

* 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;

?

/*

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

* 依赖Timer和TimerTask这两个类:

* 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); // null,[email protected]

????????System.out.println(s2);// null,[email protected]

????}

}

?

?

????????????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); // [email protected]

????????System.out.println(t2);// [email protected]

????}

}

?

?

?

????(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;

* ????}

* }

*/

?

?

时间: 2024-08-04 18:43:57

javaSE第二十四天的相关文章

centos LNMP第二部分nginx、php配置 第二十四节课

centos  LNMP第二部分nginx.php配置  第二十四节课 上半节课 下半节课 f

centos mysql 优化 第二十四节课

centos mysql  优化  第二十四节课 f

第二十四课:能量和功率

1.RC电路充电过程的能量特性: 电源提供的能量  Vs i 在T内积分 如果T远远大于时间常数,则该能量等于 CVs2 但是电容储存的能量等于 (1/2) CVs2 因此一半能量被电阻消耗,另一半则被电容储存起来 2.RC电路放电过程的能量特性: 所以能量消耗在电阻上 3.将两个过程相连,则电源消耗CVs2,一般在充电时消耗,一般在放电时消耗 因此平均功率等于 CVs2f   ,f是充放电的切换频率,愈大功率越大 4.类似于MODFET反相电路 两种功率之和:待机功率和动态功率,后者就是充放电

经典算法题每日演练——第二十四题 梳排序

原文:经典算法题每日演练--第二十四题 梳排序 这篇再看看一个经典的排序,梳排序,为什么取名为梳,可能每个梳都有自己的gap吧,大梳子gap大一点,小梳子gap小一点. 上一篇我们看到鸡尾酒排序是在冒泡排序上做了一些优化,将单向的比较变成了双向,同样这里的梳排序也是在冒泡排序上做了一些优化. 冒泡排序上我们的选择是相邻的两个数做比较,就是他们的gap为1,其实梳排序提出了不同的观点,如果将这里的gap设置为一定的大小, 效率反而必gap=1要高效的多. 下面我们看看具体思想,梳排序有这样一个1.

Gradle 1.12用户指南翻译——第二十四章. Groovy 插件

其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc/tree/1.12. 直接浏览双语版的文档请访问: http://gradledoc.qiniudn.com/1.12/userguide/userguide.html. 另外,Android 手机用户可通过我写的一个程序浏览文档,带缓存功能的,兼容

第二十四节,自定义函数

第二十四节,自定义函数函数是将要实现的功能写在函数里,在要使用此功能的地方调用此函数即可实现功能,这样大大减少编程重复书写同样的代码,在多个要使用同样功能的地方调用函数即可不需要重复写同样的代码函数式编程最重要的是增强代码的重用性和可读性 函数的定义主要有如下要点: def:表示函数的关键字函数名:函数的名称,日后根据函数名调用函数函数体:函数中进行一系列的逻辑计算,如:发送邮件.计算出 [11,22,38,888,2]中的最大数等...参数:为函数体提供数据return:返回值:当函数执行完毕

Egret入门学习日记 --- 第二十四篇(书中 9.12~9.15 节 内容)

第二十四篇(书中 9.12~9.15 节 内容) 开始 9.12节 内容. 重点: 1.TextInput的使用,以及如何设置加密属性. 操作: 1.TextInput的使用,以及如何设置加密属性. 创建exml文件,拖入组件,设置好id. 这是显示密码星号处理的属性. 创建绑定类. 实例化,并运行. 但是焦点在密码输入框时,密码是显示的. 暂时不知道怎么设置 “焦点在密码框上时,还是显示为 * 号” 的方法. 至此,9.12节 内容结束. 开始 9.13节 . 这个,和TextInput的使用

第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题

第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题 1.原题呈现 2.试题答案 3.题目解析 因博客园无法打出公式等,所以给你们几个小编推荐的链接去看看,在这里小编深感抱歉! https://blog.csdn.net/Lu_Anlai/article/details/85490641 https://blog.csdn.net/Ronaldo7_ZYB/article/details/83098444 来源:CSDN 编辑:疯狂的杰克 原文地址:https://www.cnblo

第二十四章

希言自然.飘风不终朝,骤雨不终日.孰为此?天地,天地而弗能久,又况于人乎?故从事而道者同于道,德者同于德,失者同于失.同于德者,道亦德之.同于失者,道亦失之. 第二十四章1 为何盛世的领导者很少有丰功伟绩? 各位朋友大家好,今天我们接着来聊<道德经>.前边大家的留言我都看了,写的感想我也看了,我真的没想到大家感想写的这么好.而且这个<道德经>给大家带来这么多的变化.这么多的提升,让我特别开心,真的非常感动.我自己在讲<道德经>的过程中,说实话我自己也在不断地提升.也在学