zoukankan      html  css  js  c++  java
  • 线程池、线程安全

    线程的匿名内部类

      匿名内部类对象格式:

        new 父类类型(){

          抽象父类的方法、
        }
        最终得到的就是父类类型的子类对象

      有两种方式,1:创建线程对象时,直接重写Thread类中的run方法

    1 // 继承thread//创建线程任务和线程对象    
    2         new Thread(){
    3             public void run() {                
    4                 for (int i = 0; i <100; i++) {
    5                     System.out.println(Thread.currentThread().getName()+":"+i);
    6                 }
    7             }
    8         }.start();

            2:使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法

    Runnable r=new Runnable(){
                public void run(){
                    for (int i = 0; i <100; i++) {
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            };
            //创建线程对象
            Thread t=new Thread(r);
            //开启线程
            t.start();

    线程池

      为了避免重复的创建线程,线程池的出现可以让线程进行复用。通俗点讲,当有工作来,就会向线程池拿一个线程,当工作完成后,并不是直接关闭线程,而是将这个线程归还给线程池供其他任务使用。

      线程池的使用我们主要是通过Runnable接口、Callable接口来实现;

      Runnable接口的使用:

        1.从线程池工厂(Executor)对象中获取线程池(ExecutorService)对象

        2.让线程池对象从池子中选一条空闲的线程执行线程任务,没有等待,用完放回

        3.没有对象销毁线程池

    1         MyRunnable mr=new MyRunnable();
    2         ExecutorService es=Executors.newFixedThreadPool(2);
    3         ExecutorService es2=Executors.newFixedThreadPool(10);
    4         es.submit(mr);
    5         es.submit(mr);
    6         es.submit(mr);
    7         es2.submit(mr);
    8         es.shutdown();
    9         es2.shutdown();

      Callable接口的使用:

        与Runnable接口功能相似,用来指定线程的任务。其中的call()方法,用来返回线程任务执行完毕后的结果,call方法可抛出异常。

        这里讲一下Future接口,他用来记录线程任务执行完毕后产生的结果。线程池创建与使用,Runnable接口和Callable接口都可以使用。

        例:

     1 //创建线程任务
     2         MyCallable mc=new MyCallable();
     3         //获取线程池对象
     4         ExecutorService es=Executors.newFixedThreadPool(2);
     5         //获取future对象
     6         Future<String> f = es.submit(mc);
     7         //从future对象中获取返回值
     8         String s=f.get();
     9         System.out.println(s);
    10         //销毁线程池
    11         es.shutdown();

      MyCallable.java:

        

       运行之后得到的是返回值

     线程安全

      当若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

      线程同步的方式有两种:一是同步代码块,二是同步方法;

      同步代码块:在代码块声明上 加上synchronized

        基本格式:

          synchronized(非匿名的任意对象){

                线程要操作的共享数据

          }

        例:

     1 //创建锁对象
     2     private Object obj=new Object();
     3     public void run() {
     4         while(true){
     5             synchronized (obj) {
     6                 
     7             
     8         if (ticket>0) {
     9             try {
    10                 Thread.sleep(300);
    11             } catch (InterruptedException e) {
    12                 // TODO Auto-generated catch block
    13                 e.printStackTrace();
    14             }
    15             System.out.println(Thread.currentThread().getName()+"窗口卖了第"+ticket--+"张票");
    16         }
    17     }
    18     }
    19     }

        synchronized(obj)中的obj相当于是一个同步锁,没有get到锁的线程不能进入同步,在同步中的线程如果没有运行到synchronized的最后,则不会释放锁

        另外,加上了线程同步之后,程序的运行速度会明显减慢

      同步方法(推荐)
        将线程共享数据,同步,抽取到一个方法中,在方法的声明处加入同步关键字
        省去synchronized中的 非匿名任意对象,而这个obj对象由本类对象引用this隐式代替,只是没有写出来而已。
     
        基本格式:
          public synchronized void method(){

               可能会产生线程安全问题的代码

          }

       Lock接口

        提供了获得锁lock()和释放锁unlock()两个方法
        基本步骤:
          1.创建lock对象
          2.获取锁
          3.可能会产生线程安全问题的代码
          4.释放锁
        
        
        

      

  • 相关阅读:
    C# Task ContinueWith的实现
    C# Task 是什么?返回值如何实现? Wait如何实现
    C# ExecutionContext 实现
    C# Barrier 实现
    C# CountdownEvent实现
    C# SemaphoreSlim 实现
    C# ManualResetEventSlim 实现
    C# Monitor实现
    C# SpinLock实现
    C# SpinWait 实现
  • 原文地址:https://www.cnblogs.com/zhai113/p/11780863.html
Copyright © 2011-2022 走看看