Java多线程深入理解学习笔记之九-----多线程实现方法3及简单使用计时器来删除指定的文件夹

多线程程序实现方案3

实现Callable接口

步骤和刚才演示线程池执行Runnable对象的差不多。

但是还可以更好玩一些,求和案例演示

好处:

可以有返回值

可以抛出异常

弊端:

代码比较复杂,所以一般不用

下面是使用Callable接口实现的一个累加计算的小程序实现代码:

package cn.itcast_10;

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();
	}
}
package cn.itcast_10;

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

}

匿名内部类方式使用多线程

匿名内部类方式使用多线程

new Thread(){代码…}.start();

new Thread(new Runnable(){代码…}).start();

package cn.itcast_11;

/*
 * 匿名内部类的格式:
 * 		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();
        //相当于重写了run()方法,打印word+i
	}
}

定时器

定时器是一个应用十分广泛的线程工具,可用于调度多个定时任务以后台线程的方式执行。在Java中,可以通过TimerTimerTask类来实现定义调度的功能

Timer

public Timer()


TimerTask

public abstract void run()

public boolean cancel()

开发中

Quartz是一个完全由java编写的开源调度框架。

使用计时器实现的一个定时删除指定文件夹的程序代码:

package 定时器删除文件夹;

import java.io.File;
import java.util.Date;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;

public class TextDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in = new Scanner(System.in);
		Timer timer = new Timer();
		System.out.print("请输入您要删除文件的位置: ");
		String FilePath = in.nextLine();
		System.out.println("请输入您要删除文件的指定时间(yyyy-MM-dd-hh-mm): ");
		String time = in.next();
		Date date = new Date(
				Integer.valueOf(time.substring(0, 4))-1900,
				Integer.valueOf(time.substring(5, 7))-1,
				Integer.valueOf(time.substring(8, 10)),
				Integer.valueOf(time.substring(11, 13)),
				Integer.valueOf(time.substring(time.lastIndexOf('-')+1))
				);
		System.out.println(date.toLocaleString());
		timer.schedule(new TaskDemo(timer,FilePath), date);
		
	}

}

class TaskDemo extends TimerTask {
	private Timer timer = null;
	private String FilePath = null;
	/**
	 * 递归删除文件夹
	 * @param FilePath
	 */
	public void delete(String FilePath) {
		File file = new File(FilePath);
		if (file.exists()) {
			// 删除
			File[] files = file.listFiles();
			for (File file2 : files) {
				if (file2.isFile()) {
					System.out.println("成功删除: "+file2.getName()+" "+file2.delete());
				} else if (file2.isDirectory()) {
					delete(file2.getPath());
				}
			}
			file.delete();
		} else {
			System.out.println("您输入的文件夹/文件不存在~");
		}
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		delete(FilePath);
		timer.cancel();
	}

	public TaskDemo() {

	}

	public TaskDemo(Timer timer, String FilePath) {
		this.timer = timer;
		this.FilePath = FilePath;
	}

}

运行效果:

多线程常见的面试题

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:线程的生命周期图(图解)
    新建 -- 就绪 -- 运行 -- 死亡
    新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡
   

猜你喜欢

转载自blog.csdn.net/acDream_/article/details/81586697
今日推荐