学习内容总结(week 5)

1.集合的结构

2.集合的子实现类

3.异常

4.二分搜索法

5.线程

6.同步机制


1.集合的结构



2.集合的子实现类

1)LinkedList
    特有功能:
       public void addFirst(Object e):在列表开头插入元素;
       public void addLast(Object e):将元素追加到列表的末尾;
       public Object getFirst():获取列表的第一个元素;
       public Object getLast():获取列表的最后一个元素 ;
       public Object removeFirst(): 删除列表的第一个元素,并获取第一个元素;
       public Object removeLast():删除列表的最后一个元素,并获取最后一个元素;
       
       例:
           public class LinkedListDemo {

            public static void main(String[] args) {

        LinkedList<String> link = new LinkedList<>() ;

       // public void addFirst(Object e):在列表开头插入元素

       link.addFirst("hello") ;
       link.addFirst("world") ;
       link.addFirst("JavaEE") ;

       //public Object getFirst():获取列表的第一个元素
        System.out.println(link.getFirst());
        System.out.println(link.getLast());

        // public Object removeFirst(): 删除列表的第一个元素,并获取第一个元素
        System.out.println(link.removeFirst());
        System.out.println(link.removeLast());
    }
}

2)HashSet
    应用场景:
           在一些需求中,如果没有明确要求元素重复,那就可以使用hashSet,保证元素唯一;
           类型:String,Integer,Long,....常用类都已经重写了hashCode和equals方法.
       
       例:
           public class HashSetDemo {

            public static void main(String[] args) {

        HashSet<Student> hs1 = new HashSet<>() ;

        Student s1 = new Student("宋江",35) ;
        Student s2 = new Student("宋江",35) ;
        Student s3 = new Student("武松",30) ;
        Student s4 = new Student("宋江",30) ;
        Student s5 = new Student("武松",30) ;
        Student s6 = new Student("卢俊义",28) ;
        Student s7 = new Student("卢俊义",28) ;
        System.out.println("-------------------------------");

        //添加集合中
        hs1.add(s1) ;
        hs1.add(s2) ;
        hs1.add(s3) ;
        hs1.add(s4) ;
        hs1.add(s5) ;
        hs1.add(s6) ;
        hs1.add(s7) ;

        //遍历
        for(Student s : hs1){
            System.out.println(s.getName()+"---"+s.getAge());
        }
    }
}
     (注意:自定义的 Student 类中,已重写 hashCode()和 equals,否则不能保证唯一)
     
3)TreeSet
    a.public TreeSet():构造一个空的树,实现元素自然排序 (取决于存储的元素类型能否实现Comparable接口);
    例:
        public class TreeSetDemo {
    public static void main(String[] args) {

        //创建TreeSet,无参构造方法
        TreeSet<Student> ts = new TreeSet<>() ;

        Student s1 = new Student("gaoyuanyuan",42) ;
        Student s2 = new Student("gaoyuanyuan",42) ;
        Student s3 = new Student("jacky",40) ;
        Student s4 = new Student("rose",40) ;
        Student s5 = new Student("tomcat",35) ;
        Student s6 = new Student("jeffry",35) ;
        Student s7 = new Student("liushishi",54) ;
        Student s8 = new Student("liudehua",60) ;

     //因为当前集合存储的自定义对象,元素要实现自然排序必须所在的类实现Compareable接口
        ts.add(s1) ;  
        ts.add(s2) ;
        ts.add(s3) ;
        ts.add(s4) ;
        ts.add(s5) ;
        ts.add(s6) ;
        ts.add(s7) ;
        ts.add(s8) ;

        //遍历
        for(Student s : ts){
            System.out.println(s.getName()+"---"+s.getAge());
        }
    }
}
    public class Student implements  Comparable<Student>{

    private String name ;
    private int age ;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {//重写 toString
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //排序的代码
    @Override
    public int compareTo(Student s) { //

        //年龄int类型
        //主要条件为年龄
       int num = this.age - s.age ;

        //次要条件:年龄相同,还要比较姓名的内容是否相同
     int num2 = (num==0)?(this.name.compareTo(s.name)):num;                //此处对字符串以字典顺序比较
        return num2 ;
    }
}
    b.比较强排序:
       public TreeSet(Comparator<? super E> comparator)
 
           Comparator是一个接口类型
              1)自定义一个类实现Comparator接口,重写compare方法
              2)使用接口的匿名内部类(推荐)
     
     例:
         public class TreeSetDemo {

    public static void main(String[] args) {
        
      //  public TreeSet(Comparator<? super E> comparator)
      //MyComparator myComparator = new MyComparator() ; //

        //接口的匿名内部类
         TreeSet<Student>  ts = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //主要条件:按照学生的年龄从小到大排序

              int num = s1.getAge() - s2.getAge() ;
             //如果年龄相同,比较姓名是否一样
           int num2 = (num==0)? (s1.getName().compareTo(s2.getName())): num ;

                return num2;
            }
        }) ;

        //创建几个学生对象
        Student s1 = new Student("gaoyuanyuan",42) ;
        Student s2 = new Student("gaoyuanyuan",42) ;
        Student s3 = new Student("jacky",40) ;
        Student s4 = new Student("rose",40) ;
        Student s5 = new Student("tomcat",35) ;
        Student s6 = new Student("jeffry",35) ;
        Student s7 = new Student("liushishi",54) ;
        Student s8 = new Student("liudehua",60) ;

        ts.add(s1) ;
        ts.add(s2) ;
        ts.add(s3) ;
        ts.add(s4) ;
        ts.add(s5) ;
        ts.add(s6) ;
        ts.add(s7) ;
        ts.add(s8) ;

        for (Student s:ts) {
            System.out.println(s.getName()+"---"+s.getAge());
        }
    }
}

4)Map
    遍历功能:
       方式1  Set<K> keySet() :获取当前Map集合中的所有的键的集合 
                     V get(Object key):通过键获取值
       方式2  Set<Map.Entry<K,V>> entrySet():获取所有键值对对象
                    通过键值对象 获取键 /获取值
                    V getValue()
        例:
            public class MapDemo {

    public static void main(String[] args) {

        //创建Map集合对象
        Map<String,String> map = new HashMap<>() ;

        //添加元素
        map.put("令狐冲","东方不败") ;
        map.put("杨过","小龙女") ;
        map.put("陈玄风","梅超风") ;
        map.put("郭靖","黄蓉") ;

        // Set<K> keySet()  :获取当前Map集合中的所有的键的集合
        Set<String> keySet = map.keySet(); 
        //增强for遍历
        for(String key: keySet){
            //获取所有的键的元素
            //  V get(Object key):通过键获取值
            String value = map.get(key);
            System.out.println(key+"="+value);
        }


        //方式2:
        //Set<Map.Entry<K,V>> entrySet()
        Set<Map.Entry<String, String>> entry = map.entrySet();
        //增强for:遍历键值对对象获取到
        for(Map.Entry<String, String> en: entry){
            //获取键和值
            //K getKey()
           // V getValue()
            String key = en.getKey();
            String value = en.getValue();
            System.out.println(key+"="+value);
        }
    }
}

5)List
    静态功能:
          public static <T extends Comparable<? super T>> void sort(List<T> list):按照自然升序排序(针对List集合排序)
           public static <T> void sort(List<T> list,Comparator<? super T> c):按照比较器排序针对List集合
           public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T>:获取当前自然顺序中List的最大值
           public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T>:最小值
           public static void reverse(List<?> list):对List集合顺序反转
           public static void shuffle(List<?> list):随机置换
 
     例:
         public class CollectionsDemo {
    public static void main(String[] args) {

        //创建List集合
        List<Integer> list = new ArrayList<>() ;

        //添加元素
        list.add(10) ;
        list.add(50) ;
        list.add(15) ;
        list.add(25) ;
        list.add(5) ;
        list.add(12) ;

        System.out.println(list);

        System.out.println("---------------------------------");
        //public static <T extends Comparable<? super T>> void sort(List<T> list):
        Collections.sort(list);
        System.out.println(list);
        System.out.println("----------------------------------");
        //public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T>
        Integer max = Collections.max(list);
        System.out.println(max);
        System.out.println("----------------------------------");
        System.out.println(Collections.min(list));
        System.out.println("-----------------------------------");
        Collections.reverse(list);//反转
        System.out.println(list);
        System.out.println("------------------------------------");
        //  public static void shuffle(List<?> list):随机置换
        Collections.shuffle(list);
        System.out.println(list);

    }
}


3.异常

编译时期异常和运行时期异常(RuntimeException):程序在运行过程中出现问题(代码书写不严谨)
    异常的处理两种方式:

             标准格式:try...catch...finally
 
             变形格式
                  try{
                  //可能出现问题的代码
                  }catch(异常类名 变量名){
                  //处理异常
                   }
                         
                   try{
                    //可能出现问题的代码
                   }catch(异常类名 变量名){
                    //处理异常1
                     }catch(异常类名 变量名){
                     //处理异常2
                     }

                //多线程:jdk5以后:Lock:接口 (锁:可重复入的互斥锁)
                    try{
                    //可能出现问题的代码
                    }finally{
                    //释放资源(系统资源)
                     }
           throws:抛出
           
      例:
          public class ExceptionDemo1 {

    public static void main(String[] args) {

            int a = 10 ;
            int b = 0 ;  
            System.out.println(a/b);
            System.out.println("over");
        }catch(ArithmeticException e){  //捕获异常:可以使用大的Exception,但是捕获:具体异常具体捕获
            System.out.println("除数不能为0");
        }
    }
}

*面试题:
    throws和throw的区别?
 
    a.共同点:都是抛出
    
    b. 用法不同:
        1)使用位置不同
           throws:
                  a)将异常抛出在方法声明上;
                  b)在方法名的后面可以跟多个异常类名,中间逗号隔开;
           throw:
                  a)在方法的语句体中某个逻辑语句中;
                  b)它后面只能跟异常对象,而不是类名;
 
 
        2)调用者是否处理不同
           throws:调用者必须进行显示处理(try...catch/throws),否则报错;
           throw:调用者无须显示处理,一般情况都是在逻辑语句进行处理;
 
          3)出现异常是否肯定性
           throws:在方法上的,执行某个方法的代码中,可能有问题(表示出现异常的一种可能性);
           throw:执行某段代码一定会执行这个异常(表示出现异常的一种肯定性);;
 
        4)
            throws:将具体的处理交给jvm,通过jvm吧异常信息打印控制台上,显示的底层源码而且会显示当前错误消息字符串;
 
            throw:程序中某段代码有问题:只是打印异常类名(jvm处理).


4.二分搜索法

public class BinarySearch {

        public static void main(String[] args) {
        int[] arr = {11,22,33,44,55} ;
        //调用二分搜索方法查询
        int index = binarySearch(arr, 22);
        System.out.println(index);

    }
    //返回值int
    //方法参数:数组,查询的元素
    public static int binarySearch(int[] arr,int target){
        //防止空指针异常
        if(arr!=null){
            //定义数组的最小索引:
            int min = 0 ;
            //定义最大索引
            int max = arr.length -1 ;
            //使用循环while
            while(min<=max){
                //计算中位点索引
                int mid = (min+max)/2 ;
                //如果当前中位点对应的元素小于要要查找的元素
                if(target < arr[mid]){
                    //左半区域:继续折半
                    max = mid -1 ;
                }else if(target > arr[mid]){
                    //右边区域:继续折半
                    min = mid + 1 ;
                }else{
                    //查询到了
                    return mid ;
                }
            }
        }
        //循环结束之后,还没有找,则返回-1
        return -1 ;
    }
}


5.线程

1) 创建线程的实现 方式1:
        1)将一个类声明为Thread的子类
        2) 这个子类应该重写Thread类的run方法
        3)然后可以分配并启动子类的实例,用start()启动
        
        例:
            public class MyThread extends Thread {

        //重写Thread类的方法
            @Override
        public void run() {
        //run方法里面:一般情况耗时的操作
        for(int x = 0 ; x < 200 ; x ++){
            System.out.println(x);
        }
    }
}
        public class ThreadDemo {
    public static void main(String[] args) {

        MyThread my1 = new MyThread() ;//第一个线程对象
        MyThread my2 = new MyThread() ; //第二个线程对象

     my1.start();//start():有jvm调用底层run方法,出现并发执行
     my2.start();
    }
}

 2) 创建线程的实现 方式2:
      1)自定义类实现Runnable接口;
     2)重写Runnable接口的run方法;
     3)在main用户线程中
           可以分配类的实例(创建类的实例)
     4)创建当前类对象,然后创建Thread类对象,将当前类对象作为参数来传递
           当前类---->"资源共享类"
           Thread(Runnable target, String name);
     5)分别启动线程.
     
     例:
         public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for(int  x = 0 ; x < 100 ; x ++){       System.out.println(Thread.currentThread().getName()+":"+x);
        }
    }
}
        
        public class ThreadDemo {
    public static void main(String[] args) {
        //可以分配类的实例(创建类的实例)
        MyRunnable my  = new MyRunnable() ; //资源类:被多线程共享//具体类new 具体类

        //创建两个线程类对象
        Thread t1  = new Thread(my,"卡卡罗特") ;
        Thread t2  = new Thread(my,"贝吉塔") ;

        //分别启动线程
        t1.start();
        t2.start();
    }
}

3)安全问题
    检验多线程安全问题的标准;
      1)是否是多线程环境是不能更改,使用多线程实现;
      2)是否存在共享数据是(资源类的数据: tickets)必须要有共享数据;
      3)是否存在多条语句对共享数据的操作→是,可操作

       解决----Java提供同步机制:同步代码块 将多条对共享数据包裹起来
                   synchronized(锁对象){
                      将多条对共享数据包裹起来
                  }
   锁对象:必须要多个线程使用的同一个锁对象,而不是分别自己的锁对象!
   
   例:
       public class SellTicket implements Runnable {

    //成员变量;100张票
    public static int tickests = 100 ;

    //创建一个锁对象:
    public Object obj = new Object() ;


    //t1,t2,t3
    @Override
    public void run() {
        //模拟一直票
        while(true){

            //t1,t2,t3
            //解决方案:
            //将多条语句对共享数据的操作包裹起来
            //synchronized (new Object()){  //锁对象 :三个线程分别使用自己的锁
                //必须为是同一个锁对象
           synchronized (obj){
                //模拟网络延迟
                //判断
                if(tickests>0){//100>0
                    try {
                        Thread.sleep(100); //单位为毫秒数
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    //输出窗口信息
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickests--)+"张票");
                }
            }
        }

    }
}

    public class SellTicketTest {

    public static void main(String[] args) {
        //创建资源类对象SellTicket
        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();
    }
}


4)同步方法
    如果一个方法的方法体的第一句话就是同步代码块;
   可以将synchronized关键字提取到方法声明上,跟在权限修饰符的后面;
   权限修饰符 synchronized 返回值类型 方法名(形式列表){   //非静态的同步方法
        业务逻辑...
    }
    例:
        在方法内:synchronized (obj){}// 此类需要新建锁对象
                public Object obj = new Object();
        在方法声明上: synchronized(this){}// 非静态同步;
                    synchronized(类名.class){}//静态同步
                    
                    
5)死锁问题处理
    a.死锁例:  
      创建锁对象: 
     public class MyMonitor {
    //提供两把锁对象
    public static final Object objA = new Object() ;
    public static final Object objB = new Object() ;
}
    
    public class DieLock implements Runnable {

    private boolean flag  ;//标记值
    public DieLock(boolean flag){
        this.flag = flag ;
    }

    @Override
    public void run() {
        //判断标记值
        //t1 ---->DieLock(true)
        //t2 ---->DieLock(false)
        if(flag){
            //t1
            synchronized (MyMonitor.objA){
                System.out.println("if ObjeA");//"if objA"
                    synchronized (MyMonitor.objB){
                        System.out.println("if objB");
                    }
            }
        }else
            //t2
            synchronized (MyMonitor.objB){
                System.out.println("else ObjB"); 
                synchronized (MyMonitor.objA){
                    System.out.println("else objA");      
                }
            }
        }

    }
}

        public class DieLockDemo {

    public static void main(String[] args) {

        //创建资源类对象
        DieLock d1 = new DieLock(true) ;
        DieLock d2 = new DieLock(false) ;

        //创建Thread里对象
        Thread t1 = new Thread(d1) ;
        Thread t2 = new Thread(d2) ;

        //分别启动
        t1.start();
        t2.start();
    }
}

        以上各自创建锁对象,导致死锁,只能执行一次代码就锁住了!
        
    
    b. 解决死锁例: "卖包子"实例1
        public class StuffBun {
    //成员变量不私有化
    String name ;//包子的类型(肉包子,菜包子)
    String bunType ;//大包子/小包子
}


    public class SetBun implements  Runnable {

    //声明这个包子类
    private StuffBun stu ;
    public SetBun(StuffBun stu){
        this.stu = stu ;
    }

    //定义一个统计变量
    int x = 0 ;

    @Override
    public void run() {
        //产生包子
      /*  StuffBun stu = new StuffBun() ;
        stu.name = "肉包子" ;
        stu.bunType = "大类型";*/
      //不断的产生数据
      while(true){
          synchronized (stu){
              if(x % 2 == 0){//t1
                  stu.name = "肉包子" ;
                  stu.bunType = "大包子";
              }else{
                  stu.name = "菜包子" ;
                  stu.bunType = "小包子" ;
              }
          }
          x ++ ;
      }
    }
}


            public class GetBun implements Runnable {
    //声明包子类的变量stb
    private StuffBun stb ;
    public GetBun( StuffBun stb){
        this.stb = stb ;
    }

    @Override
    public void run() {

        //模拟要使用数据
      //  StuffBun stb = new StuffBun() ;
        //不断使用数据
        while(true){
            synchronized (stb){
                System.out.println(stb.name+"---"+stb.bunType);
            }

        }
    }
}


        public class ThreadDemo {
    public static void main(String[] args) {

        //创建一个包子对象
        StuffBun sbu  = new StuffBun() ; //同一个对象

        //创建生产资源类对象
        SetBun sb = new SetBun(sbu) ;
        //消费者资源类对象
        GetBun gb = new GetBun(sbu) ;

        //创建线程了对象
      Thread t1 = new Thread(sb) ;//生产者资源类所在的生产者线程
      Thread t2 = new Thread(gb) ;//消费者资源类所在的消费者线程

        t1.start();
        t2.start();

    }
}

    核心:将包子通过生产资源类或者消费者资源类,通过构造方法传递,通用一个包子对象!
    
    
    c.解决死锁例(且wait()/notify()实现同步): "卖包子"实例2
        例:
            public class StuffBun {
    //成员变量不私有化
    private  String name ;//包子的类型(肉包子,菜包子)
    private String bunType ;//大包子/小包子

    //定义标记:表示是否存在包子数据
    private boolean flag ; //默认false,没有数据

    //提供给包子数据进行赋值的方法
    public synchronized void set(String name,String bunType){ //锁对象是this:非静态的同步方法
        //如果当前生产者没有语句,需要等待生成产生数据
        if(this.flag){
            //锁对象调用wait发那个发
            try {
                this.wait();//释放锁对象...
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //赋值
        this.name = name ;
        this.bunType = bunType ;
        //如果现在有数据了
        //改变信号
        this.flag  = true ;//有数据类
        //通知(唤醒)消费者线程,赶紧使用数据
        this.notify(); //唤醒对方线程
    }
    //提供方法:获取包子的数据
    public synchronized void get(){ //非静态的同步方法:锁对象 this
        //如果当前消费资源类中存在包子数据,先等待消费使用完毕数据
        if(!this.flag){
            //等待使用完毕数据
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(this.name+"---"+this.bunType);
        //改变信号值
        //如果包子消费完毕
        this.flag = false ;
        //唤醒对方线程(生产者资源类,别等了,产生数据)
        this.notify();
    }
}


        public class SetBun implements  Runnable {

    //声明这个包子类
    private StuffBun stu ;
    public SetBun(StuffBun stu){
        this.stu = stu ;
    }

    //定义一个统计变量
    int x = 0 ;

    @Override
    public void run() {
        //产生包子
      /*  StuffBun stu = new StuffBun() ;
        stu.name = "肉包子" ;
        stu.bunType = "大类型";*/
        //不断的产生数据
        while(true){

            if(x % 2 == 0){//t1
                //stu.name = "肉包子" ;
                //stu.bunType = "大包子";
                stu.set("肉包子","大包子");
            }else{
                //stu.name = "菜包子" ;
                //stu.bunType = "小包子" ;
                stu.set("菜包子","小包子");
            }
            x ++ ;
        }
    }
}


        public class GetBun implements Runnable {
    //声明包子类的变量stb
    private StuffBun stu ;
    public GetBun( StuffBun stu){
        this.stu = stu ;
    }

    @Override
    public void run() {

        //模拟要使用数据
        //  StuffBun stb = new StuffBun() ;
        //不断使用数据
        while(true){
            stu.get();//获取包子数据

        }
    }
}


        public class ThreadDemo {
    public static void main(String[] args) {
        //创建一个包子对象
        StuffBun sbu  = new StuffBun() ; //同一个对象
        //创建生产资源类对象
        SetBun sb = new SetBun(sbu) ;
        //消费者资源类对象
        GetBun gb = new GetBun(sbu) ;
        //创建线程了对象
      Thread t1 = new Thread(sb) ;//生产者资源类所在的生产者线程
      Thread t2 = new Thread(gb) ;//消费者资源类所在的消费者线程

        t1.start();
        t2.start();

    }
}

6)Lock/Unlock
    提供比syncrhonized方法(/同步代码块)更具体的锁定操作,多个线程并发访问,抢占共享资源数据,通过lock实现多个线程对某个共享资源进行独占访问,不会有安全问题.
    
    例:
        import java.util.concurrent.locks.Lock;
        import java.util.concurrent.locks.ReentrantLock;

public class SellTicket implements  Runnable {

    //定义100张票
    private static int tickets = 100 ;

    //创建一个锁对象
    Lock lock = new ReentrantLock() ;

    @Override
    public void run() {
        //模拟一只有票
        while(true){

            //通过锁对象--->获取锁
            lock.lock();
            //try...catch...finaly:捕获异常
            //使用try..finally
            try{
                //判断
                if(tickets>0){

                    //睡眠100毫秒
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }                  System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"张票");
                }else{
                    break ;
                }
            }finally {
                //释放锁
                lock.unlock();
            }
        }
    }
}

public class LockDemo {

    public static void main(String[] args) {
            //创建共享资源类对象
        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();
    }
}


7)线程池
        特点:
         在内存中创建一个固定可重用的线程数,当前线程执行完毕终止了,不会被回收掉,再次回到线程池中,等待下一次利用.
         通过 工厂类:
           Exceutors
          创建一个固定的可重用的线程数,返回值就线程池对象
          public static ExecutorService    =  newFixedThreadPool(int nThreads)
          
          例:
              import java.util.TreeMap;
            import java.util.concurrent.Callable;

    public class MyCallable implements Callable {
    @Override
    public Object call() throws Exception {
        for(int x = 0 ; x < 100 ; x++){
            System.out.println(Thread.currentThread().getName()+":"+x);
        }

        return null;
    }
}

    
        import java.util.concurrent.Callable;
        import java.util.concurrent.ExecutorService;
        import java.util.concurrent.Executors;
public class ThreadPoolDemo {
    public static void main(String[] args) {

        //通过工厂类创建线程池对象
        ExecutorService threadPool = Executors.newFixedThreadPool(3);

        //提交异步方法
        //MyRunnable:打印x的值0-99之间的数据,不需要返回结果
        //  threadPool.submit(new MyRunnable()) ;
        //  threadPool.submit(new MyRunnable()) ;
        //   <T> Future<T> submit(Callable<T> task)
        //Callable:提交异步计算---需要重写Callable的call来计算结果;如果没有结果,直接在call无须返回

        threadPool.submit(new MyCallable()) ;
        threadPool.submit(new MyCallable()) ;
        threadPool.submit(new MyCallable()) ;

        //void shutdown()关闭线程池
        threadPool.shutdown();
    }
}


6.同步机制

为了解决线程安全问题,存在4种方法
  1)synchronized(锁对象){多条语句共享数据操作}
  
  2)ThreadLocal<T>:jdk8后提供本地线程类相同的线程,使用的实例一致,不同线程对象,他的ThreadLocal实例不同;
  
  3)volatil 也是同步的一种:修饰成员变量,线程对象每次执行的时候,会重复读取被volatile的变量;
  
  4)wait()+notify():实现同步,线程等待→唤醒对方线程.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值