第一章线程管理

 

第一章线程管理

 

1.1、同步、异步

 

同步:多个线程一个一个执行

 

异步:多个线程一起抢着执行

 

1.2、线程的创建和运行

 

创建线程的方式:

 

1、继承Thread类,并且覆盖run()方法

 

2、实现Runnable接口的类。使用带参数的Thread构造器来创建Thread对象。这个参数就是Runnable接口的一个实现对象

 

示例:

 

public class ThreadCalculator extends Thread{

   

    @Override

    public void run() {

        System.out.println("开启一个线程,并在线程中做一些事情");

        System.out.println("ThreadName="+Thread.currentThread().getName());

    }

 

 

public class ThreadMain {

    public static void main(String[] args) {

        for(int i=0;i<10;i++){

            ThreadCalculator tc = new ThreadCalculator();

            tc.start();

        }

    }

}

 

 

 

public class Calculator implements Runnable {

 

    private int number;

   

    public Calculator(int number) {

       this.number=number;

    }

   

    @Override

    public void run() {

       for (int i=1; i<=10; i++){

           System.out.println("ThreadName="+Thread.currentThread().getName()+" "+number+" * "+i+" = "+(i*number));

       }

    }

 

}

 

public class Main {

 

    public static void main(String[] args) {

 

       for (int i=1; i<=10; i++){

           Calculator calculator=new Calculator(i);

           Thread thread=new Thread(calculator);

           thread.start();

       }

    }

}

 

 

 

 

 

1.3、线程信息的获取和设置

 

ID:线程的唯一标识符

 

Name:线程名称

 

Priority:线程的优先级,1~10之间,数值越高优先级越高。

 

Status:线程的状态。线程有6种状态:new、runnable、blocked、waiting、time waiting、terminated

 

 

 

public class Calculator implements Runnable {

 

    private int number;

   

    public Calculator(int number) {

        this.number=number;

    }

   

    @Override

    public void run() {

            System.out.printf("%s:  %d\n",Thread.currentThread().getName(),number,number);

    }

 

}

 

 

public class Main {

   

    public static void main(String[] args) {

       

        Thread threads[] = new Thread[10];

       

        for (int i=0; i<10; i++){

            threads[i]=new Thread(new Calculator(i));

            if ((i%2)==0){

                threads[i].setPriority(Thread.MAX_PRIORITY);

            } else {

                threads[i].setPriority(Thread.MIN_PRIORITY);

               

            }

            threads[i].setName("Thread "+i);

        }

       

        for (Thread thread : threads) {

            System.out.println("Thread-ID:" + thread.getId() + " Thread-Name:"+thread.getName() + " Thread Status:"+thread.getState());

        }

        System.out.println("--------------------------------------------------------------------------");

        for (Thread thread : threads) {

            thread.start();

            System.out.println("Thread-ID:" + thread.getId() + " Thread-Name:"+thread.getName() + " Thread Status:"+thread.getState());

        }

       

    }

 

}

 

 

 

1.4、线程的中断

 

public class PrimeGenerator extends Thread{

 

    @Override

    public void run() {

       

        while (true) {

            System.out.println("Threadn-Name"+Thread.currentThread().getName());

            // When is interrupted, write a message and ends

            if (isInterrupted()) {

                System.out.println("The Prime Generator has been Interrupted\n");

                return;

            }

        }

    }

 

}

 

 

public class Main {

 

    public static void main(String[] args) {

 

        Thread task=new PrimeGenerator();

        task.start();

       

        try {

            TimeUnit.SECONDS.sleep(5);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

       

        task.interrupt();

    }

 

}

 

 

 

 

 

1.5、线程中断的控制

 

程序分析:以下程序主要是通过throw new InterruptedException();控制被run调用的方法,来终止被调用方法的继续执行,并非是终止线程!!!

 

 

public class FileSearch implements Runnable {

 

    private String initPath;

   

    private String fileName;

 

    public FileSearch(String initPath, String fileName) {

        this.initPath = initPath;

        this.fileName = fileName;

    }

 

    @Override

    public void run() {

        File file = new File(initPath);

        if (file.isDirectory()) {

            try {

                directoryProcess(file);

            } catch (InterruptedException e) {

                System.out.printf("%s: The search has been interrupted",Thread.currentThread().getName());

                cleanResources();

            }

        }

    }

 

    private void cleanResources() {

 

    }

 

    private void directoryProcess(File file) throws InterruptedException {

 

        File list[] = file.listFiles();

        if (list != null) {

            for (int i = 0; i < list.length; i++) {

                if (list[i].isDirectory()) {

                    directoryProcess(list[i]);

                } else {

                    fileProcess(list[i]);

                }

            }

        }

        if (Thread.interrupted()) {

            throw new InterruptedException();

        }

    }

 

    private void fileProcess(File file) throws InterruptedException {

        if (file.getName().equals(fileName)) {

            System.out.printf("%s : %s\n",Thread.currentThread().getName() ,file.getAbsolutePath());

        }

       

        if (Thread.interrupted()) {

            throw new InterruptedException();

        }

    }

 

}

 

 

 

 

public class Main {

 

    public static void main(String[] args) {

        FileSearch searcher=new FileSearch("C:\\","autoexec.bat");

        Thread thread=new Thread(searcher);

       

        thread.start();

       

        try {

            TimeUnit.SECONDS.sleep(10);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

       

        thread.interrupt();

    }

 

}

 

 

 

1.6、线程的休眠和恢复

 

以下程序通过interrupt()方法来打断sleep休眠

Sleep是让程序挂起休眠

public class FileClock implements Runnable {

 

     @Override

     public void run() {

         for (int i = 0; i < 10; i++) {

              System.out.printf("%s\n", new Date());

              try {

                   TimeUnit.SECONDS.sleep(1);

              } catch (InterruptedException e) {

                   System.out.println("The FileClock has been interrupted");

              }

         }

     }

}

 

public class Main {

 

     public static void main(String[] args) {

         FileClock clock=new FileClock();

         Thread thread=new Thread(clock);

        

         thread.start();

         try {

              TimeUnit.SECONDS.sleep(5);

         } catch (InterruptedException e) {

              e.printStackTrace();

         };

        

         thread.interrupt();

     }

}

 

 

 

1.7、等待线程的终止

 

 

 

thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。

也就是说,下面的线程会等待上面的线程执行结束再去执行

 

class RunnableJob implements Runnable {

 

    @Override

    public void run() {

        Thread thread = Thread.currentThread();

        try {

            Thread.sleep(1000);

            System.out.println(thread.getName() + " end" + " at "  + new Date());

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

 

}

 

public class BasicTest {

    public static void main(String[] args) throws InterruptedException {

        //初始化

        RunnableJob runnableJob = new RunnableJob();

        Thread T1 = new Thread(runnableJob, "T1");

        Thread T2 = new Thread(runnableJob, "T2");

        Thread T3 = new Thread(runnableJob, "T3");

       

        //T2在T1执行完后执行,T3在T2执行完后执行

        T1.start();

        T1.join();

       

        T2.start();

        T2.join();

       

        T3.start();

    }

 

}

 

 

 

 

 

1.8、守护线程的创建和运行

 

守护线程适合做监控等后台操作

public class Event {

 

    private Date date;

   

    private String event;

   

    public Date getDate() {

        return date;

    }

   

    public void setDate(Date date) {

        this.date = date;

    }

   

    public String getEvent() {

        return event;

    }

   

    public void setEvent(String event) {

        this.event = event;

    }

}

 

 

public class WriterTask implements Runnable {

   

    Deque<Event> deque;

   

    public WriterTask (Deque<Event> deque){

        this.deque=deque;

    }

   

    @Override

    public void run() {

       

        for (int i=1; i<100; i++) {

            Event event=new Event();

            event.setDate(new Date());

            event.setEvent("线程="+Thread.currentThread().getId()+"被创建");

           

            deque.addFirst(event);

            try {

                TimeUnit.SECONDS.sleep(1);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

}

 

 

 

 

public class CleanerTask extends Thread {

 

    private Deque<Event> deque;

 

    public CleanerTask(Deque<Event> deque) {

        this.deque = deque;

        setDaemon(true);

    }

 

    @Override

    public void run() {

        while (true) {

            Date date = new Date();

            clean(date);

        }

    }

 

    private void clean(Date date) {

        long difference;

        boolean delete;

       

        if (deque.size()==0) {

            return;

        }

       

        delete=false;

        do {

            Event e = deque.getLast();

            difference = date.getTime() - e.getDate().getTime();

            if (difference > 10000) {

                System.out.println("清除事件: "+e.getEvent());

                deque.removeLast();

                delete=true;

            }

        } while (difference > 10000);

        if (delete){

            System.out.println("清除后队列大小:"+deque.size());

        }

    }

}

 

 

 

 

public class Main {

 

    public static void main(String[] args) {

       

        Deque<Event> deque=new ArrayDeque<Event>();

       

        WriterTask writer=new WriterTask(deque);

        for (int i=0; i<3; i++){

            Thread thread=new Thread(writer);

            thread.start();

        }

       

        CleanerTask cleaner=new CleanerTask(deque);

        cleaner.start();

 

    }

 

}

 

 

 

1.9、线程中不可控异常的处理

 

在java中有两种异常

1、  非运行时异常:必须throws抛出或者捕获,比如IOException、ClassNotFoundException

2、  运行时异常:不必显示处理,是程序执行的过程中出现的异常。

 

因为run()方法不支持throws抛出异常,所以如果是非运行时必须处理时候,只能通过捕获来处理

如果出现运行时异常,会导致线程退出程序,需要手动去捕获处理异常,这里有两种方式,一种是手动try。。。catch,还有一种就是下面要讲解的在线程上设置捕获异常。

public class Task implements Runnable {

   

    @Override

    public void run() {

        int numero=Integer.parseInt("TTT");

    }

 

}

 

 

 

public class ExceptionHandler implements UncaughtExceptionHandler {

   

    @Override   

    public void uncaughtException(Thread t, Throwable e) {

        System.out.printf("An exception has been captured\n");

        System.out.printf("Thread: %s\n",t.getId());

        System.out.printf("Exception: %s: %s\n",e.getClass().getName(),e.getMessage());

        System.out.printf("Stack Trace: \n");

        e.printStackTrace(System.out);

        System.out.printf("Thread status: %s\n",t.getState());

    }

 

}

 

 

 

 

 

public class Main {

 

    public static void main(String[] args) {

        Task task=new Task();

        Thread thread=new Thread(task);

        thread.setUncaughtExceptionHandler(new ExceptionHandler());

        thread.start();

       

        try {

            thread.join();

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

       

        System.out.printf("Thread has finished\n");

 

    }

 

}

 

 

 

 

 

1.10、线程局部变量的使用

 

通过继承Thread或者实现Runnable借口中,使用普通属性,会出现数据共享并发问题

可以通过ThreadLocal Variable线程局部变量来实现每个线程使用自己的单独属性

异常程序:count被累加了,说明是共享的

public class UnsafeTask implements Runnable{

 

    public int count=1;

   

    @Override

    public void run() {

        count++;

       

    }

 

}

 

public class Main {

 

    public static void main(String[] args) {

        UnsafeTask task=new UnsafeTask();

       

        for (int i=0; i<10; i++){

            Thread thread=new Thread(task);

            thread.start();

           

        }

       

        System.out.println(task.count);

    }

}

正确程序:count没有被累加,说明不是共享的

public class SafeTask implements Runnable {

 

    public static ThreadLocal<Integer> count= new ThreadLocal<Integer>() {

        protected Integer initialValue(){

            return 1;

        }

    };

   

    @Override

    public void run() {

        count.set(count.get()+1);

    }

 

}

 

public class SafeMain {

 

    public static void main(String[] args) {

        SafeTask task=new SafeTask();

       

        for (int i=0; i<10000; i++){

            Thread thread=new Thread(task);

            thread.start();

        }

       

        System.out.println(task.count.get());

       

    }

 

}

 

 

 

1.11、线程的分组

 

ThreadGroup tg = new ThreadGroup("ThreadGroup测试");

      ThreadTask task1 = new ThreadTask();

      ThreadTask task2 = new ThreadTask();

      ThreadTask task3 = new ThreadTask();

     

      Thread t1 = new Thread(tg,task1);

      Thread t2 = new Thread(tg,task2);

      Thread t3 = new Thread(tg,task3);

     

      t1.start();

      t2.start();

      t3.start();

 

1.12、线程组中不可控异常的处理

 

public class Task implements Runnable {

 

    @Override

    public void run() {

        Random random=new Random(Thread.currentThread().getId());

        while (true) {

            int result=1000/((int)(random.nextDouble()*1000));

            if (Thread.currentThread().isInterrupted()) {

                System.out.printf("%d : Interrupted\n",Thread.currentThread().getId());

                return;

            }

        }

    }

}

 

 

public class MyThreadGroup extends ThreadGroup {

 

    public MyThreadGroup(String name) {

        super(name);

    }

 

    @Override

    public void uncaughtException(Thread t, Throwable e) {

        interrupt();

    }

}

 

 

public class Main {

 

    public static void main(String[] args) {

 

        MyThreadGroup threadGroup=new MyThreadGroup("MyThreadGroup");

        Task task=new Task();

        for (int i=0; i<2; i++){

            Thread t=new Thread(threadGroup,task);

            t.start();

        }

    }

 

}

 

1.13、使用工厂类创建线程

 

 

 

public class Task implements Runnable {

 

    @Override

    public void run() {

        System.out.println(Thread.currentThread().getName());

    }

 

}

 

public class MyThreadFactory implements ThreadFactory {

 

    private int counter;

    private String name;

   

    public MyThreadFactory(String name){

        counter=0;

        this.name=name;

    }

   

    @Override

    public Thread newThread(Runnable r) {

        Thread t=new Thread(r,name+"-Thread_"+counter);

        counter++;

        return t;

    }

   

}

 

public class Main {

 

    public static void main(String[] args) {

        MyThreadFactory factory=new MyThreadFactory("MyThreadFactory");

        Task task=new Task();

       

        for (int i=0; i<110; i++){

            Thread thread = factory.newThread(task);

            thread.start();

        }

       

    }

 

}

 

 

 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑石课堂

请给我打钱!!!谢谢,不客气!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值