博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
滴水穿石-09多线程
阅读量:4683 次
发布时间:2019-06-09

本文共 25493 字,大约阅读时间需要 84 分钟。

1:多线程概述

  私以为多线程就是一个进程中同时又多个线程执行,就是“多线程”。从代码的角度理解就是一个程序中有多个方法同时运行。(可能不是很准确)

2:多线程实现方案

  创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。

       创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。

2.1 继承Thread 类  

1:创建MyThread继承Thread类2:重写run()方法3:创建对象4:启动线程
步骤

 MyThread 1.0

package d9;public class MyThreadDemo {    public static void main(String[] args) {        //创建线程对象        MyThread my = new  MyThread();        MyThread my2 = new  MyThread();        //my.run();        //my.run();         //run() 方法仅仅是封装该线程执行的代码,直接调用是管道方法        //start() 方法首先启动了线程,然后再由jvm去掉用该线程的run方法        my.start();        my2.start();    }}
MyThreadDemo 1.0

2.2 继承Runnable接口

1:自定义一个类MyRunnable实现Runnable接口2:重写run()方法3:创建MyRunnable类的对象4:创建Threadle的对象,并把3创建的对象以参数形式传递
步骤
package d9;public class MyRunnable implements Runnable {    @Override    public void run() {        // TODO Auto-generated method stub        for (int i = 0; i < 100; i++) {            System.out.println(Thread.currentThread().getName()+":"+i);        }    }}
Runnable
package d9;public class MyRunnableDemo {    public static void main(String[] args) {         MyRunnable my = new MyRunnable();         Thread t1 = new Thread(my);         Thread t2 = new Thread(my,"李四");                  t1.setName("张三");                 t1.start();         t2.start();    }}
MyRunnableDemo

 

2.3 Callable,会在线程池部分讲解

3:设置和获取线程名称

package d9;public class MyThread extends Thread {    public MyThread() {}    public MyThread(String name) {        super(name);    }    @Override    public void run() {        // TODO Auto-generated method stub        for (int i = 0; i < 100; i++) {            System.out.println(getName()+" : "+ i);        }    }}
MyThread
package d9;public class MyThreadDemo {    public static void main(String[] args) {        //创建线程对象        MyThread my = new  MyThread("逍遥");        MyThread my2 = new  MyThread();        //my.run();        //my.run();         //run() 方法仅仅是封装该线程执行的代码,直接调用是管道方法        //start() 方法首先启动了线程,然后再由jvm去掉用该线程的run方法            my2.setName("小天狼");//给线程命名        my.start();        my2.start();                //输出当前线程的方法名臣        System.out.println(Thread.currentThread().getName());    }}
MyThreadDemo

 

4:线程调度和线程控制

 4.1线程调度

package d9;public class ThreadPriority extends Thread {@Overridepublic void run() {    // TODO Auto-generated method stub    for (int i = 0; i <100; i++) {        System.out.println(getName()+": "+i);    }}}
ThreadPriority
package d9;public class ThreadPriorityDemo {    public static void main(String[] args) {        //创建线程对象        MyThread my = new  MyThread("逍遥");        MyThread my2 = new  MyThread();                 my2.setName("小天狼");//给线程命名        my.start();        my2.start();        //线程优先级的范围1-10默认为5        my2.setPriority(1);             }}
ThreadPriorityDemo

 4.2线程控制

  4.2.1 线程休眠

package d9;import java.util.Date;public class ThreadSleep extends Thread {    @Override    public void run() {        // TODO Auto-generated method stub         for (int i = 0; i < 10; i++) {            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }                        System.out.println(getName()+":"+i+"当前时间"+new Date());        }    }}
ThreadSleep
package d9;public class ThreadSleepDemo {        public static void main(String[] args) {        // TODO Auto-generated method stub        ThreadSleep s1 = new ThreadSleep();        ThreadSleep s2 = new ThreadSleep();        ThreadSleep s3 = new ThreadSleep();                s1.setName("张三");        s2.setName("李四");        s3.setName("王五");                s1.start();        s2.start();        s3.start();    }}
ThreadSleepDemo

 

  4.2.2 线程加入 

package d9;public class ThreadJoin extends Thread {    @Override    public void run() {        // TODO Auto-generated method stub        for (int i = 0; i < 100; i++) {            System.out.println(getName()+" : "+ i);        }    }}
ThreadJoin
package d9;public class ThreadJoinDemo {        public static void main(String[] args) {        // TODO Auto-generated method stub        ThreadJoin s1 = new ThreadJoin();        ThreadJoin s2 = new ThreadJoin();        ThreadJoin s3 = new ThreadJoin();                s1.setName("张三");        s2.setName("李四");        s3.setName("王五");                s1.start();        try {            s1.join();        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        s2.start();        s3.start();    }}
ThreadJoinDemo

  4.2.3 线程礼让(并不能完全实现)

package d9;public class ThreadYield extends Thread {         @Override    public void run() {        // TODO Auto-generated method stub        for (int i = 0; i < 100; i++) {            System.out.println(getName()+" : "+ i);            Thread.yield();        }    }}
ThreadYield
package d9;public class ThreadYieldDemo {    public static void main(String[] args) {        //创建线程对象        ThreadYield my = new  ThreadYield();        ThreadYield my2 = new  ThreadYield();                 my.setName("逍遥");;        my2.setName("小天狼");//给线程命名        my.start();        my2.start();             }}
ThreadYieldDemo

 

  4.2.4 后台线程(守护线程)

package d9;public class ThreadDaemon extends Thread {         @Override    public void run() {        // TODO Auto-generated method stub        for (int i = 0; i < 100; i++) {            System.out.println(getName()+" : "+ i);                     }    }}
ThreadDaemon
package d9;public class ThreadDaemonDemo {    public static void main(String[] args) {        //创建线程对象        ThreadDaemon my = new  ThreadDaemon();        ThreadDaemon my2 = new  ThreadDaemon();                 my.setName("逍遥");;        my2.setName("小天狼");         my.setDaemon(true);        my2.setDaemon(true);        my.start();        my2.start();                Thread.currentThread().setName("杨小可");        for(int x=0;x<5;x++) {            System.out.println(Thread.currentThread().getName());        }    }}
ThreadDaemonDemo

 

  4.2.5 中断线程

package d9;public class ThreadInterruptDemo {    public static void main(String[] args) {        //创建线程对象        ThreadInterrupt my = new  ThreadInterrupt();                  my.setName("逍遥");;             my.start();        //超过3秒如果不醒来,就停止        try {            Thread.sleep(3000);            my.interrupt();        } catch (InterruptedException e) {            e.printStackTrace();        }    }}
ThreadInterruptDemo
package d9;import java.util.Date;public class ThreadInterrupt extends Thread {         @Override    public void run() {                 System.out.println("开始执行: "+new Date());        try {            Thread.sleep(10000);        } catch (InterruptedException e) {            System.out.println("线程被终止了 ");        }        System.out.println("结束执行: "+new Date());    }}
ThreadInterrupt

 5 线程的生命周期

  5.1 简单生命周期

新建:创建线程对象就绪:有执行资格,没有执行权运行:有执行资格,有执行权        阻塞:由于一些操作让线程保护欲了该状态,没有执行资格,没有执行权                而另一些操作却可以把它激活,激活后处于就绪状态死亡:线程对象变成垃圾,等待被回收
线程状态

 5.2 

常见的几种情况

A:新建—就绪—运行—结束

B:新建—就绪—运行—就绪—运行--结束
C:新建—就绪—运行—其他阻塞--就绪—运行—结束
D:新建—就绪—运行—同步阻塞--就绪—运行—结束
E:新建—就绪—运行—等待阻塞--同步阻塞--就绪—运行--结束

6 练习题

  6.1 模拟电影票售票系统

  6.1.1 版本1.0

package d9;public class SellTicket implements Runnable {    //定义一个资源 100张票    int ticketNumber = 100;        @Override    public void run() {        // TODO Auto-generated method stub        while (true) {            if (ticketNumber>0) {                System.out.println(Thread.currentThread().getName()+"正在出售第"+ticketNumber+"张票");                ticketNumber--;            }else {                break;            }        }    }}
SellTicket
package d9;public class SellTicketDemo {    public static void main(String[] args) {        // TODO Auto-generated method stub        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();    }}
SellTicketDemo

  6.1.2版本2.0 

  由1.0可以查看出有重复票卖出.这时候应该用static定义一个全局变量

6.1.3 同步代码块

 线程安全分析:由于该线程是多线程的,而且有共享资源(100张票).并且有多条语句操作共享数据(三个窗口).所以会存在安全隐患

同步代码块:        synchronized(对象){         需要同步的代码;    }
同步代码块

同步方法:即把同步关键字加在方法上,此时的锁对象是this

静态方法的锁对象是累的字节码文件,即SellTicket.class

6.1.4 锁

 6.1.5 死锁:两个锁资源由于相互调用而出现相互等待的现象

1 package d9;2 3 public class MyLock {4     //第一步,创建两把锁对象5     public static final Object objA = new Object();6     public static final Object objB = new Object();7 }
创建两把锁对象
1 package d9; 2  3 public class DieLock extends Thread { 4     private boolean flag; 5     public  DieLock (boolean flag) { 6         this.flag = flag;                 7     } 8     public void run() { 9          if (flag) {10             synchronized (MyLock.objA) {11                 System.out.println("if objA");12                 synchronized(MyLock.objB) {13                     System.out.println("if objB");14                 }15             }16         }else {17             synchronized (MyLock.objB) {18                 System.out.println("else objB");19                 synchronized(MyLock.objA) {20                     System.out.println("else objA");21                 }22             }23         }24     }25 }
DieLock
package d9;public class DieLockDemo {    public static void main(String[] args) {        // TODO Auto-generated method stub        DieLock di1 = new DieLock(true);        DieLock di2 = new DieLock(false);                di1.start();        di2.start();    }}
DieLockDemo

 7 生产者消费者模式

1:资源类(Student)2:生产者(SetThread)3:消费者(GetThread)4:测试类
思路

7.1 Version1.0

package StudentLX;public class Student {    //创建一个资源类,Student    String name;    int age;}
Student
package StudentLX;public class SetThread implements Runnable {    private Student s;    public SetThread(Student s) {        this.s = s;    }    @Override    public void run() {        // TODO Auto-generated method stub         s.name = "逍遥";        s.age = 18;    }}
SetThread
package StudentLX;public class GetThread implements Runnable {    private Student s ;     public GetThread (Student s) {         this.s =s;                      }    public void run() {                 System.out.println("姓名:"+s.name+"年龄: "+s.age);    }}
GetThread
package StudentLX;public class StudentDemo {    public static void main(String[] args) {        //创建资源        Student s = new Student();        //设置和获取类        GetThread gt= new GetThread(s);        SetThread st= new SetThread(s);            //创建线程        Thread t1 = new Thread(gt);         Thread t2 = new Thread(st);        //启动线程        t1.start();        t2.start();            }}
StudentDemo

多线程问题是会存在安全隐患的.进一步修改SetThread和GetThread方法

7.2 Version2.0

package StudentLX;public class SetThread implements Runnable {    private Student s;    public SetThread(Student s) {        this.s = s;    }    @Override    public void run() {        // TODO Auto-generated method stub         int i =1;        while (true) {            if (i%2==0) {                s.name = "逍遥";                s.age = 18;            }else {                s.name = "小天狼";                s.age = 22;            }            i++;        }            }}
SetThread
package StudentLX;public class GetThread implements Runnable {    private Student s ;     public GetThread (Student s) {         this.s =s;                      }    public void run() {                  while (true) {             System.out.println("姓名: "+s.name+";---: "+s.age);                     }            }}
GetThread

原因分析以及解决方法

A:多线程环境;B:共享同一资源;C共用同一代码.

解决方法线程同步:A:不同种类的线程都要加锁(GetThread和SetThread);B不同种类的线程加同一把锁

package StudentLX;public class SetThread implements Runnable {    private Student s;    public SetThread(Student s) {        this.s = s;    }    @Override    public void run() {        // TODO Auto-generated method stub        int i = 1;        while (true) {            synchronized (s) {                if (i % 2 == 0) {                    s.name = "逍遥";                    s.age = 18;                } else {                    s.name = "小天狼";                    s.age = 22;                }                i++;            }        }    }}
SetThread
package StudentLX;public class GetThread implements Runnable {    private Student s ;     public GetThread (Student s) {         this.s =s;                      }    public void run() {                  while (true) {             synchronized (s) {                 System.out.println("姓名: "+s.name+";---: "+s.age);                             }                     }            }}
GetThread

 

  

7.3 Version3.0 等待唤醒机制

思路:

  A:生产者  先看是否有数据,有就等待;没有就生产,生产完之后通知消费者进行消费

  B:消费者  先看是否有数据,有就消费;没有就等待,通知生产者生产数据

等待唤醒

Object类中提供了三个方法

  wait():等待

  notify():唤醒单个线程

  notifyAll():唤醒所有线程

package StudentLX;public class Student {    //创建一个资源类,Student    boolean flag;//定义一个标志,用于判断是否有数据    String name;    int age;}
Student中定义一个标签
package StudentLX;public class SetThread implements Runnable {    private Student s;        public SetThread(Student s) {        this.s = s;    }    @Override    public void run() {        // TODO Auto-generated method stub        int i = 1;        while (true) {            synchronized (s) {                //生产者:如果有就等待 ;如果没有就生产;                if (s.flag) {                    try {                        s.wait();                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                if (i % 2 == 0) {                    s.name = "逍遥";                    s.age = 18;                } else {                    s.name = "小天狼";                    s.age = 22;                }                i++;                s.flag=true;                //生产完成,通知消费者(唤醒线程)                s.notify();            }        }    }}
SetThread进行改造
package StudentLX;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) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                 System.out.println("姓名: "+s.name+";---: "+s.age);                         //修改标记                 s.flag=false;                 s.notify();            }                     }            }}
GetThread方法进行改造
package StudentLX;public class StudentDemo {    public static void main(String[] args) {        //创建资源        Student s = new Student();        //设置和获取类        GetThread gt= new GetThread(s);        SetThread st= new SetThread(s);            //创建线程        Thread t1 = new Thread(gt);         Thread t2 = new Thread(st);        //启动线程        t1.start();        t2.start();            }}
测试类不变

 7.4  version4.0   Student变量私有化

package StudentLX;public class Student {    // 第一步,修改为私有成员    private boolean flag;//      private String name;    private int age;    //第二步,创建SetStudent方法,并设置为同步方法    public synchronized void  setStudent(String name,int age) {        //如果存在,等待         if (this.flag) {            try {                this.wait();            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }         //创建        this.name = name;        this.age = age;        //修改标签        this.flag=true;        //唤醒        this.notify();    }    public synchronized void getStudent() {        //如果不存在,等待         if (!this.flag) {            try {                this.wait();            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }         //使用         System.out.println(this.name+"---"+this.age);        //修改标签        this.flag=false;        //唤醒        this.notify();            }          }
Student
package StudentLX;public class SetThread implements Runnable {    private Student s;        public SetThread(Student s) {        this.s = s;    }    @Override    public void run() {        // TODO Auto-generated method stub        int i = 1;        while (true) {                             if (i % 2 == 0) {                    s.setStudent("逍遥", 18);                } else {                    s.setStudent("小天狼", 22);                }                i++;                             }        } }
SetThread
package StudentLX;public class GetThread implements Runnable {    private Student s ;     public GetThread (Student s) {         this.s =s;                      }    public void run() {                  while (true) {              s.getStudent();             }            }}
GetThread
package StudentLX;public class StudentDemo {    public static void main(String[] args) {        //创建资源        Student s = new Student();        //设置和获取类        GetThread gt= new GetThread(s);        SetThread st= new SetThread(s);            //创建线程        Thread t1 = new Thread(gt);         Thread t2 = new Thread(st);        //启动线程        t1.start();        t2.start();            }}
StudentDemo

8 线程组:多个线程组合到一起

package d9;public class MyRunnable implements Runnable {    @Override    public void run() {        // TODO Auto-generated method stub        for (int i = 0; i < 100; i++) {            System.out.println(Thread.currentThread().getName()+":"+i);        }    }}
MyRunnable
package d9;public class ThreadGroupDemo {    public static void main(String[] args) {        // 获取线程所属线程组的名称        method1();        // 设置线程所属的线程组        method2();    }    private static void method2() {        // 创建一个线程组        ThreadGroup tg = new ThreadGroup("新的线程组");        MyRunnable my = new MyRunnable();        // 创建线程对象,并分组        Thread t1 = new Thread(tg, my, "逍遥new");                 Thread t2 = new Thread(tg, my, "小天狼new");                 // 输出线程名称        System.out.println(t1.getThreadGroup().getName()  );        System.out.println(t2.getThreadGroup().getName()  );        // 通过线程组控制该组内的所有线程,例如:设置优先级和后台线程        tg.setMaxPriority(4);    }    private static void method1() {        MyRunnable my = new MyRunnable();        Thread t1 = new Thread(my, "逍遥");        Thread t2 = new Thread(my, "小天狼");        // 获取线程的所属线程组        ThreadGroup gt1 = t1.getThreadGroup();        ThreadGroup gt2 = t2.getThreadGroup();        // 通过ThreadGroup中的getName()方法获取线程组名称        String name1 = gt1.getName();        String name2 = gt2.getName();        System.out.println(name1);        System.out.println(name2);        // 获取main线程的线程组名称        System.out.println(Thread.currentThread().getThreadGroup().getName());    }}
ThreadGroupDemo

 9 线程池

9.1 通过实现Runnable接口

A:创建一个线程池对象,控制要创建几个线程对象    public static ExecutorService newFixedThreadPoll(int nThreads) B:这种线程池的线程可以执行    可以执行Runnable对象或者Callable对象代表的线程    做一个类实现Runnable接口C:调用如下方法    Future
submit(Runnable task)
Future
subbmit(Callable
task)
步骤
package d9;public class MyRunnable implements Runnable {    @Override    public void run() {        // TODO Auto-generated method stub        for (int i = 0; i < 100; i++) {            System.out.println(Thread.currentThread().getName()+":"+i);        }    }}
MyRunnable
package d9;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;class ExecutorsDemo {    public static void main(String[] args) {        // 创建线程池        ExecutorService tpool = Executors.newFixedThreadPool(2);        //创建线程对象,并放入到线程池中        tpool.submit(new MyRunnable());        tpool.submit(new MyRunnable());        //结束线程池        tpool.shutdown();    }}
ExecutorsDemo

 9.2 通过实现Callable接口

package d9;import java.util.concurrent.Callable;public class MyCallable implements Callable {    @Override    public Object call() throws Exception {         for (int i = 0; i < 100; i++) {             System.out.println(Thread.currentThread().getName()+":"+i);        }                 return null;    }}
MyCallable
package d9;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CallableDemo {    public static void main(String[] args) {        //创建线程池对象        ExecutorService pool = Executors.newFixedThreadPool(2);                pool.submit(new MyCallable());        pool.submit(new MyCallable());    }    }
CallableDemo

 9.3 通过实现Callable接口实现具有返回值的线程池(求和)

package d9;import java.util.concurrent.Callable;public class MyCallable implements Callable
{ private int startNumber; private int endNumber; public MyCallable(int startNumber,int endNumber) { this.startNumber = startNumber; this.endNumber = endNumber; } @Override public Integer call() throws Exception { int sum=0; for (int i = startNumber; i <= endNumber; i++) { sum+=i; } return sum; }}
MyCallable
package d9;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class CallableDemo {    public static void main(String[] args) throws InterruptedException, ExecutionException {        //创建线程池对象        ExecutorService pool = Executors.newFixedThreadPool(2);            Future
sum1= pool.submit(new MyCallable(1,100)); Future
sum2= pool.submit(new MyCallable(1,50)); int f1 = sum1.get(); System.out.println(f1); System.out.println(sum2.get()); } }
CallableDemo

 10 匿名内部类实现多线程

package d9;public class ThreadAnonymous {    public static void main(String[] args) {        // 01 继承Thread类 实现多继承        new Thread() {            public void run() {                for (int i = 0; i < 100; i++) {                    System.out.println("Hello" + i);                }            };        }.start();        // 02 通过实现runable接口来实现        new Thread(new Runnable() {            @Override            public void run() {                for (int i = 0; i < 100; i++) {                    System.out.println("World" + i);                }            }        }) {        }.start();        // 03 混合实现,其实只走方法内部的        new Thread(new Runnable() {            @Override            public void run() {                for (int i = 0; i < 100; i++) {                    System.out.println("java" + i);                }            }        }) {            public void run() {                for (int i = 0; i < 100; i++) {                    System.out.println("!!" + i);                }            };        }.start();    }}
ThreadAnonymous

 11 定时线程

   定时器:可以在指定的时间做某件事情,还可以重复做某件事情

  依赖Timer(定时)和TimerTask(任务)这两个类

import java.util.Timer;import java.util.TimerTask;public class TimeDemo {    public static void main(String[] args) {        //创建定时器对象        Timer t = new Timer();        //执行任务        t.schedule(new MyTask(), 3000);    }}class MyTask extends TimerTask{    @Override    public void run() {        // TODO Auto-generated method stub        System.out.println("beng,爆炸了!!!");    }}
version 1.0
import java.util.Timer;import java.util.TimerTask;public class TimeDemo {    public static void main(String[] args) {        //创建定时器对象        Timer t = new Timer();        //执行任务+结束任务        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() {        // TODO Auto-generated method stub        System.out.println("beng,爆炸了!!!");        t.cancel();    }}
version 2.0 可以自动结束任务
import java.util.Timer;import java.util.TimerTask;public class TimeDemo {    public static void main(String[] args) {        //创建定时器对象        Timer t = new Timer();        //执行任务+结束任务        //3秒后执行爆炸任务,如果不成功,每个2秒后再继续炸        t.schedule(new MyTask(), 3000,2000);    }}class MyTask extends TimerTask{         @Override    public void run() {        // TODO Auto-generated method stub        System.out.println("beng,爆炸了!!!");             }}
Version 3.0 连环炸

 练习:定时删除指定文件夹

package d9;import java.io.File;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Iterator;import java.util.Timer;import java.util.TimerTask;public class FolderDelete {    public static void main(String[] args) throws ParseException {        //创建定时器对象        Timer t = new Timer();        //执行任务         String stTime = "2018-3-30 07:21:06";        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        Date d = sdf.parse(stTime);        t.schedule(new DeleteFolder(), d,100000);    }}class DeleteFolder extends TimerTask{         @Override    public void run() {         File srcFolder = new File("D:\\aaa");         deleteFolder(srcFolder);        System.out.println("beng,爆炸了!!!");             }    private void deleteFolder(File srcFolder) {        // TODO Auto-generated method stub        File [] fileArray = srcFolder.listFiles();        if (fileArray != null) {            for (File file : fileArray) {                if (file.isDirectory()) {                    deleteFolder(file);                }else {                    file.delete();                }            }            srcFolder.delete();        }    }}
View Code

 

转载于:https://www.cnblogs.com/YK2012/p/8504052.html

你可能感兴趣的文章
Git for Android Studio 学习笔记
查看>>
pip 警告!The default format will switch to columns in the future
查看>>
Arrays类学习笔记
查看>>
实验吧之【天下武功唯快不破】
查看>>
2019-3-25多线程的同步与互斥(互斥锁、条件变量、读写锁、自旋锁、信号量)...
查看>>
win7-64 mysql的安装
查看>>
dcm4chee 修改默认(0002,0013) ImplementationVersionName
查看>>
闲的折腾——自己动手更换油雾分离阀/废气阀
查看>>
maven3在eclipse3.4.2中创建java web项目
查看>>
发布时间 sql语句
查看>>
黑马程序员 ExecuteReader执行查询
查看>>
记一些从数学和程序设计中体会到的思想
查看>>
题目1462:两船载物问题
查看>>
POJ 2378 Tree Cutting(树形DP,水)
查看>>
第二冲刺阶段个人博客5
查看>>
UVA 116 Unidirectional TSP (白书dp)
查看>>
第三方测速工具
查看>>
MySQL 网络访问连接
查看>>
在aws ec2上使用root用户登录
查看>>
数据访问 投票习题
查看>>