您的位置:首页 > 其它

D24

2016-04-22 21:47 267 查看
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:线程的生命周期图
新建 -- 就绪 -- 运行 -- 死亡
新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡
建议:画图解释。

/*
* 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,
* 为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock。
*
* Lock:
* void lock(): 获取锁。
* void unlock():释放锁。
* ReentrantLock是Lock的实现类.
*/
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();
}
//------------------------------------------------
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();
}
}
}
}
/*
* 分析:生产者与消费者
* 		资源类: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();
}
}
//---------------------------------------------------
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();
}
}
//--------------------------------------------------
public class GetThread implements Runnable {
private Student s;

public GetThread(Student s) {
this.s = s;
}
@Override
public void run() {
while (true) {
s.get();
}
}
}
//--------------------------------------------------
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("<span style="font-family: Arial, Helvetica, sans-serif;">林青霞2</span>", 30);
}
x++;
}
}
}
/*
*<strong> 线程池的好处</strong>:线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
*
* 如何实现线程的代码呢?
* 		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();
}
}
//---------------------------------------------------
public class MyRunnable implements Runnable {

@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}

}
/*
* 定时器:可以让我们在指定的时间做某件事情,还可以重复的做某件事情。
* 依赖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 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();
}
}

/*
* 定时器:可以让我们在指定的时间做某件事情,还可以重复的做某件事情。
* 依赖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,爆炸了");
}
}
/*
* 需求:在指定的时间删除我们的指定目录(你可以指定c盘,但是我不建议,我使用项目路径下的demo)
*/

class DeleteFolder extends TimerTask {

@Override
public void run() {
File srcFolder = new File("demo");
deleteFolder(srcFolder);
}

// 递归删除目录
public void deleteFolder(File srcFolder) {
File[] fileArray = srcFolder.listFiles();
if (fileArray != null) {
for (File file : fileArray) {
if (file.isDirectory()) {
deleteFolder(file);
} else {
System.out.println(file.getName() + ":" + file.delete());
}
}
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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  D24