12.线程间通信问题
A:等待唤醒(使用Object类中提供的三个方法)
wait():等待
notify():唤醒单个线程
notifyAll():唤醒所有线程
注意:以上三个方法需要通过锁对象调用,而锁对象可以是任意对象,所以这三个方法必须定义在Object类中
B:以生产者和消费者多线程体现
资源类:Student
设置数据类:SetThread (生产者)
获取数据类:GetThread (消费者)
测试类:StudentDemo
public class Student {
String name;
int age;
boolean flag;
}
public class SetThread implements Runnable{
private Student s;
private int x = 0;
public SetThread(Student s){
this.s = s;
}
public void run(){
while(true){
synchronized(s){
if(s.flag){
try{
s.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
if(x%2 == 0){
s.name = "高渐离";
s.age = 30;
}else{
s.name = "雪女";
s.age = 28;
}
x++;
s.flag = true;
s.notify();
}
}
}
}
public class GetThread implements Runnable{
private Student s;
public GetThread(Student s){
this.s = s;
}
public void run(){
while(true){
synchronized(s){
if(!s.flag){
try{
s.wait();
}catch(InterruptedException e){
e.printStackTrace()
}
}
System.out.println(s.name + " --- " + s.age);
s.flag = false;
s.notify();
}
}
}
}
public class StudentDemo {
public static void main(String[] args){
//创建资源对象
Sudent 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();
}
}
13.线程组
A:常用功能
ThreadGroup(String name):通过该构造方法创建线程组
Thread(ThreadGroup group,Runnable target,String name):将线程添加到线程组,并为线程组命名
public final ThreadGroup getThreadGroup():获取该线程所属线程组
public final String getName():返回该线程组名称
Thread.currentThread().getThreadGroup().getName():获取正在运行的线程所属线程组的名称
B:代码演示
public class MyRunnable implements Runnable{
public void run(){
for(int x = 0; x < 100; x++){
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}
public class ThreadGroupDemo{
public static void main(String[] args){
MyRunnable mr = new MyRunnable();
ThreadGroup tg = new ThreadGroup("线程组一");
Thread t1 = new Thread(tg,mr,"线程A");
Thread t2 = new Thread(tg,mr,"线程B");
System.out.println(t1.getThreadGroup().getName());
System.out.println(t2.getThreadGroup().getName());
//通过线程组名称设置改组线程为后台线程
tg.setDaemon(true);
t1.start();
t2.start();
}
}
14.线程池
线程池的好处:
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待先一个对象来使用
A:常用方法
创建线程池
public static ExecutorService newFixedThreadPool(int nThreads)
调用方法
Future<?> submit(Runnable task):执行Runnable对象
<T> Future<T> submit(Callable<T> task):执行Collable对象
结束线程池
void shutdown();
注意:Future<V> :表示计算结果,使用 V get() 方法获取结果
Collable 重写的是 call() 方法,该方法有返回值,返回值类型为Callable<T>泛型类型
若没有指定泛型类型,则默认使用Object类型
B:多线程的线程池实现方式
a:实现Runnable接口
public class MyRunnable implements Runnable {
public void run(){
for(int x = 0;x < 100;x++){
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}
public class ExecutorsDemo{
public static void main(String[] args){
//创建线程池,设置要创建的线程对象的数量
ExecutorService pool = Executors.newFixedThreadPool(2);
//执行Runnable对象代表的线程
pool.submit(new MyRunnable());
pool.submit(new MyRunnable());
//结束线程
pool.shutdown();
}
}
b:实现Callable<T>接口(多线程求和案例)
public class MyCollable implements Callable<Integer> {
private int number;
public MyCollable(int number){
this.number = number;
}
public Integer call() throws Exception {
int sum = 0;
for(int x = 1; x <= number; x++){
sum += x;
}
return sum;
}
}
public class CallableDemo{
public static void main(String[] args) throws InterruptedException, ExecutionException{
//创建线程池对象,设置数量
ExecutorService pool = Executors.newFixedThreadPool(2);
//执行Collable<T>对象代表的线程
Future<Integer> f1 = pool.submit(new MyCollable(100));
Future<Integer> f2 = pool.submit(new MyCollable(200));
//使用V get() 方法获取计算结果
Integer i1 = f1.get();
Integer i2 = f2.get();
//结束线程池
pool.shutdown();
}
}
15.多线程的匿名内部类实现方式
public class ThreadDemo{
public static void main(String[] args){
//基础Thread类实现多线程(使用子类对象)
new Thread(){
public void run(){
for(int x = 0; x < 100; x++){
System.our.println(Tread.currentThread().getName() + ":" +x)
}
}
}.start();
//实现Runnable接口来实现多线程(使用匿名内部类)
new Thred(new Runnable(){
public void run(){
for(int x = 0; x < 100; x++){
System.out.println(Thread.currentThread().getName() + ":" +x);
}
}
}){}.start();
}
}
注意:若同时子类对象和匿名内部类都为线程,不会报错,但只执行子类对象线程
16. 定时器
定时器:可以实现在指定的时间内做某件事,还可以实现重复的做某件事
定时器依赖Timer和TimerTask这两个类
Timer:定时
TimerTask:任务
A:常用功能
punlic Timer():创建定时器对象的构造方法
public void schedule(TimerTask task,long dalay):指定多长时间后执行任务
public void schedule(TimerTask task,long delay,long period):指定多长时间后执行任务,指定多长时间后再次执行任务
public void cancel():取消计时器任务
B:案例演示
public class TimerDemo{
public static void main(String[] args){
//创建定时器对象
Timer t = new Timer();
//执行任务
t.schedule(new MyTask(),3000,2000);
//结束任务
t.cancel()
}
}
public class MyTask extends TimerTask{
public void run(){
System.out.println("任务已执行!");
}
}
C:在指定的时间内删除指定的目录
public class TimerTest{
public static void main(String[] args) throws ParseException {
Timer t = new Timer();
String str = "2015-12-12 23:59:59";
SimpleDeteFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(s);
t.schedule(new DeleteFolder(),d);
}
}
public class DeleteFolder extends TimerTask{
public void run(){
File srcFolder = new File("demo");
deleteFolder(srcForder);
}
//递归删除目录
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());
}
}
} |
|