• java并发编程基础---Sky


    1.线程及启动和终止

    1.1 线程 -进程/优先级

       操作系统调度的最小单元是线程,线程是轻量级进程。

       线程优先级由setPriority(int)方法来设置,默认优先级是5,等级1~10.等级越高分的时间片越多。

    1.2 线程的状态

      new 初始化 》》Runable 运行》》Blocked阻塞 》》Wating等待》》 time_Wating超时等待》》 temerinated终止状态。

    1.3 Daemon辅助线程

      主线程终止后,辅助线程也就结束。thread.setDaemon(true)设置在线程开始之前。

    1.4 过期suspend() , resume(), stop()为啥不建议使用?

      suspend()调用后太霸道,不释放占有资源,而是抱着占有资源去睡觉,这样容易死锁。站着茅坑不拉屎。

      resume()、stop()不保证线程资源正常释放,那要你们何用?

      安全的终止线程:有中断操作,和自定义cancel()方法。

     1 package Thread;
     2 
     3 import java.util.concurrent.TimeUnit;
     4 
     5 /**
     6  * Created by Sky on 2016/9/22.
     7  * @author xiaoyongyong
     8  */
     9 public class Shutdown {
    10     public static void main(String[] args) throws InterruptedException {
    11         Runner one = new Runner();
    12         Thread countThread = new Thread(one,"CountThread");
    13         countThread.start();
    14         TimeUnit.SECONDS.sleep(1);
    15         countThread.interrupt();
    16 
    17         Runner two = new Runner();
    18         countThread = new Thread(two,"CountThread");
    19         countThread.start();
    20         TimeUnit.SECONDS.sleep(1);
    21         two.cancle();
    22     }
    23 
    24     private static class Runner  implements Runnable{
    25         private  long i;
    26         private volatile boolean on =true;
    27         @Override
    28         public void run() {
    29             while (on && !Thread.currentThread().isInterrupted()){
    30                 i++;
    31             }
    32             System.out.println("Count i ="+ i);
    33         }
    34         public void cancle(){
    35             on = false;
    36         }
    37     }
    38 }
    View Code

    2. 线程之间通信

    2.1 volatile 和 synchronized 关键字。

      volatile:它能保证所有线程对变量访问的可见性,即某线程对定义变量的修改,其他线程可见。谨慎使用,过多使用会降低程序运行效率。

      syncchronized:保证只有一个线程能对其定义的变量修改。保证其变量访问的可见性和排他性。

    2.2 通知/等待机制

      可以确保及时性和降低开销。

      相关方法:notify()、nitifyAll()、wait()、wait(long)、wait(long,int)。

      注意点:1)使用notify()、nitifyAll()、wait()时需要先对调用对象加锁。2)notify()、nitifyAll()方法调用后,等待线程依旧不会从wait()方法返回,

      需要调用notify()、nitifyAll()方法的线程,释放锁之后,等待线程才有机会从wait()返回。等待队列-》同步队列。3)wait()方法返回的前提是获取对象锁。

    这种机制可以运用在生产者-消费者模式中。

     1 package Thread;
     2 
     3 import java.text.SimpleDateFormat;
     4 import java.util.Date;
     5 import java.util.concurrent.TimeUnit;
     6 
     7 /**
     8  * Created by Sky on 2016/9/22.
     9  *
    10  * @author xiaoyongyong
    11  */
    12 public class WaitNotify {
    13     static boolean flag = true;
    14     static final Object lock = new Object();
    15 
    16     public static void main(String[] args) throws Exception {
    17         Thread waitTread = new Thread(new Wait(), "WaitTread");
    18         waitTread.start();
    19         TimeUnit.SECONDS.sleep(1);
    20 
    21         Thread notifyTread = new Thread(new NotifyTread(), "NotifyTread");
    22         notifyTread.start();
    23     }
    24 
    25     private static class Wait implements Runnable {
    26         @Override
    27         public void run() {
    28             synchronized (lock) {
    29                 while (flag) {
    30                     try {
    31                         System.out.println(Thread.currentThread() + " flag is true.wait. " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
    32                         lock.wait();
    33                     } catch (InterruptedException e) {
    34                         e.printStackTrace();
    35                     }
    36                 }
    37                 System.out.println(Thread.currentThread() + " flag is true.running. " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
    38             }
    39         }
    40     }
    41 
    42     private static class NotifyTread  implements Runnable {
    43         @Override
    44         public void run() {
    45             synchronized (lock){
    46                 System.out.println(Thread.currentThread() + " hold lock.notify. " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
    47                 lock.notifyAll();
    48                 flag = false;
    49                 try {
    50                     TimeUnit.SECONDS.sleep(2);
    51                 } catch (InterruptedException e) {
    52                     e.printStackTrace();
    53                 }
    54             }
    55             synchronized (lock) {
    56                 System.out.println(Thread.currentThread() + " hold lock.again.sleep " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
    57                 try {
    58                     TimeUnit.SECONDS.sleep(2);
    59                 } catch (InterruptedException e) {
    60                     e.printStackTrace();
    61                 }
    62             }
    63         }
    64     }
    65 }
    View Code

    返回结果:

    Thread[WaitTread,5,main] flag is true.wait. 22:03:45
    Thread[NotifyTread,5,main] hold lock.notify. 22:03:46
    Thread[NotifyTread,5,main] hold lock.again.sleep 22:03:48
    Thread[WaitTread,5,main] flag is true.running. 22:03:50

    2.3 管道输入/输出流

      主要用于线程之间的数据传输,传输媒介是内存,有PipedOutputStream/PipedInputStream(面向字节)  和PipedReader/PipedWriter(面向字符)。

     1 package Thread;
     2 
     3 import java.io.IOException;
     4 import java.io.PipedReader;
     5 import java.io.PipedWriter;
     6 
     7 /**
     8  * Created by Sky on 2016/9/22.
     9  * @author xiaoyongyong
    10  */
    11 public class Piped {
    12     public static void main(String[] args) throws IOException {
    13         PipedWriter out = new PipedWriter();
    14         PipedReader in = new PipedReader();
    15         out.connect(in);
    16         Thread printThread = new Thread(new Print(in), "PringThread");
    17         printThread.start();
    18 
    19         int receive;
    20         try {
    21             while ((receive = System.in.read()) != -1) {
    22                 out.write(receive);
    23             }
    24         } finally {
    25             out.close();
    26         }
    27     }
    28 
    29     private static class Print implements Runnable {
    30         private PipedReader in;
    31         public Print(PipedReader in) {
    32             this.in = in;
    33         }
    34         @Override
    35         public void run() {
    36             int receive;
    37             try {
    38                 while ((receive = in.read()) != -1) {
    39                     System.out.print((char) receive);
    40                 }
    41             } catch (IOException e) {
    42                 e.printStackTrace();
    43             }
    44         }
    45     }
    46 }
    View Code

    输入一串字符串,按enter后,将原样输出。管道输入输出流必须先连接才可复制,即connect()。

    2.4 Thread.join()的使用

      当线程A等待thread线程终止之后,才从thread.join()返回。

    join方法顾名思义 就是往线程中添加东西的;join方法可以用于临时加入线程,一个线程在运算过程中,如果满足于条件,我们可以临时加入一个线程,让这个线程运算完,另外一个线程再继续运行。

    Thread,yeld()和Thread.sleep()的区别?

      hread.yield()方法暂停当前正在执行的线程对象,并执行其他线程。也就是交出CPU一段时间(其他同样的优先级或者更高优先级的线程可以获取到运行的机会);不会释放锁资源。

      而Thread.sleep()方法使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会执行, 同时sleep函数不会释放锁资源;sleep可使优先级低的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会。

    这两个的区别在于yield只能是同级,或者高级优先执行,而sleep可以低级,同级都可以有优先执行机会。

    2.5 ThreadLocal的使用

    线程变量,是一个以TreadLocal对象为键,任意对象为值得存储结构。

    2.6 线程池技术及示例。

    以下是线程池接口的定义和实现:

    package Thread;
    
    /**
     * Created by asus on 2016/9/27.
     */
    public interface ThreadPool<Job extends Runnable> {
        void execute(Job job);
        void shutdown();
        void addWorkers(int num);
        void removeWoker(int num);
        int getJobSize();
    }
    View Code
    package Thread;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicLong;
    
    /**
     * Created by asus on 2016/9/27.
     *
     * @author xiaoyongyong
     */
    public class DefaultThreadPool<Job extends Runnable> implements ThreadPool<Job> {
        private static final int MAX_WORKER_NUMBERS = 10;
        private static final int DEFAULT_WORKER_NUMBERS = 5;
        private static final int MIN_WORKER_NUBERS = 1;
        private final LinkedList<Job> jobs = new LinkedList<Job>();
        private final List<Worker> workers = Collections.synchronizedList(new ArrayList<Worker>());
        private int workerNum = DEFAULT_WORKER_NUMBERS;
        private AtomicLong threadNum = new AtomicLong();
    
        public DefaultThreadPool() {
            initializeWorker(DEFAULT_WORKER_NUMBERS);
        }
    
        private void DefaultThreadPool(int num) {
            workerNum = num > MAX_WORKER_NUMBERS ? MAX_WORKER_NUMBERS : num < MIN_WORKER_NUBERS ? MAX_WORKER_NUMBERS : num;
            initializeWorker(workerNum);
        }
    
        @Override
        public void execute(Job job) {
            if (job != null) {
                synchronized (jobs) {
                    jobs.add(job);
                    jobs.notify();
                }
            }
        }
    
        @Override
        public void shutdown() {
            for (Worker worker : workers) {
                worker.shutdown();
            }
        }
    
        @Override
        public void addWorkers(int num) {
            synchronized (jobs) {
                if (num + this.workerNum > MAX_WORKER_NUMBERS) {
                    initializeWorker(num);
                    this.workerNum += num;
                }
            }
        }
    
        @Override
        public void removeWoker(int num) {
            synchronized (jobs) {
                if (num >= this.workerNum) {
                    throw new IllegalArgumentException("beyond workerNum");
                }
                int count = 0;
                while (count < num) {
                    Worker worker = workers.get(count);
                    if (workers.remove(worker)) {
                        worker.shutdown();
                        count++;
                    }
                }
                this.workerNum -= count;
            }
        }
    
        @Override
        public int getJobSize() {
            return jobs.size();
        }
    
        private void initializeWorker(int num) {
            for (int i = 0; i < num; i++) {
                Worker worker = new Worker();
                workers.add(worker);
                Thread threadWorker = new Thread(worker, "ThreadPool-Worker-" + threadNum.incrementAndGet());
                threadWorker.start();
            }
        }
    
    
        class Worker implements Runnable {
            private volatile boolean running = true;
    
            @Override
            public void run() {
                while (running){
                    Job job = null;
                    synchronized (jobs){
                        while (jobs.isEmpty()){
                            try {
                                jobs.wait();
                            } catch (InterruptedException e) {
                                Thread.currentThread().interrupt();
                                e.printStackTrace();
                                return;
                            }
                        }
                        job = jobs.removeFirst();
                    }
                    if(job != null){
                        job.run();
                    }
                }
            }
    
            public void shutdown() {
                running = false;
            }
        }
    }
    View Code

    2.7 基于县此次技术的简单Web服务器

    这个服务器使用main线程不断接受客户端Socket的连接,将连接以及请求交给线程池处理,这样使得Web服务器能够同同时处理多个客户端请求。

           

     

  • 相关阅读:
    体验cygwin纪实
    播布客视频PIT专用播放器MBOO2015
    rpm基本命令参考
    rhel7.x配置本地yum
    mtr网络连通性测试
    Oracle下载汇聚
    Spring Cloud心跳监测
    Hystrix的用法
    Redis系列十:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级
    dubbo异步调用三种方式
  • 原文地址:https://www.cnblogs.com/xiaoyongsz/p/5894563.html
Copyright © 2020-2023  润新知