java基础-多线程 笔记

1,java线程的创建

java线程

进程: 进程就是计算机的运行线索

线程: 进程的运行线索,计算机运行的最小单位

java中如何创建一个线程

1,1 以实现了Runable 接口的类的实例作为创建

Thread类的对象的构造函数的参数。

第一种创建线程方式

package corelesson5;
​
import corelesson4.A;
​
public class ThreadDemo1 {
    public static void main(String[] args) {
        //创建线程,就要以实现runable 接口的类的对象 作为创建 Thread 对象的构造函数的参数
          A a =new A();
        Thread t1 = new Thread(a);//  以对象作为参数,现在线程对象创建出来了
        t1.start();// 启动线程
        //  r如果直接调用run 方法 就不是线程做的事了  必须用线程对象去调用
         // 主函数本身是一个线程 我们称为主线程
      for(;;){
          System.out.println("world");
          /**  
           *  观察结果来看  两个线程都在运行
           *  t1 和main 主线程 其实在某个时间段切换运行。
           *  cpu 在单位时间点时刻,只运行一个线程, 肉眼感觉很多线程在运行
           *  cpu 来说已经很长时间了
           */
      }
    }
}
class A implements Runnable{
    /**
     * 实现runable 接口 重写run 方法
     * run 方法 就是线程要做的事情
     */
    @Override
    public void run() {// 就是线程要执行的任务
         for(;;){
             System.out.println("hello");
         }
​
    }
}

1,2创建线程方式2

直接创建类继承Thread 重写run 方法

package corelesson5;
​
public class ThreadDemo2 {
    public static void main(String[] args) {
        // 方式2 这里创建了MyThread 的对象 就是创建了线程对象
        MyThread t1 = new MyThread();
           t1.start();// 启动线程
        for(;;){
            System.out.println("world");
        }
    }
}
class MyThread extends  Thread{
    @Override
    public void run() {
        super.run();
        for (;;){
            System.out.println("hello");
        }
    }
}

两种方式都可以 建议使用第一种方式

因为 一个Runable 的实例我们就可以认为是一个任务

1.3 直接使用匿名类方式创建线程

package corelesson5;
​
public class ThreadDemo3 {
    public static void main(String[] args) {
          new Thread(new Runnable() {
              @Override
              public void run() {
                  for (;;){
                      System.out.println("hello");
                  }
              }
          }).start();
      //内部类
          new Thread(){
              public void run(){
                 for(;;){
                     System.out.println("world");
                 }
​
              }
          }.start();
​
    }
​
}

知识点1, 多线程的程序经常每次运行结果可能不一样

Runnable(Running/Ready) 跟这个状态有关系

线程顺序,

1,先来后到

2,优先级优先(拿到锁之后 优先级减一)

3,时间片轮换

2,java线程的生命周期

newBron新生状态

Pause 阻塞状态

Runable 可执行状态(Running ,Ready两种状态)

Dead (不是stop--------->死是不能复生的 )

3,java线程中常用方法

package corelesson5;
​
public class ThreadDemo4 {
    public static void main(String[] args) {
​
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
        System.out.println(t1.getName());// 获取线程的名字
        t1.setName("线程1"); // 修改线程的名字
        System.out.println(t1.getName());
        // 获取当前线程的名字
        System.out.println(Thread.currentThread().getName());
        // 获取线程优先级的等级,如果线程没有设置优先级,默认是5级
        System.out.println(t1.getPriority());
       // 优先级的范围 , 最大的是10 ,最小的是1,一般的是5,
        System.out.println(Thread.MAX_PRIORITY);
        System.out.println(Thread.MIN_PRIORITY);
        System.out.println(Thread.NORM_PRIORITY);
        
        
    }
​
}

3.2 重要的一些方法

Thread.sleep(),让线程睡,线程进入阻塞状态,不会参与竞争

package corelesson5;
​
public class ThreadDemo5 {
    public static void main(String[] args) {
​
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
​
                } catch (InterruptedException e) {
                    System.out.println("线程中断");
                }
                System.out.println("helloworld");
            }
        });
        t1.start();
        for (int i = 0; i <10 ; i++) {
            try {
                t1.sleep(10000);// 主线程sleep 10秒、、相当于Thread.sleep(10000)
             // 那个线程执行到sleep 方法 ,那个线程就去sleep
​
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
​
        }
        t1.interrupt();//  让睡眠中断 执行完以上任务之后 就唤醒线程
    }
}

interrupt 方法中断线程的睡眠,相当于唤醒

join() 方法 一个线程等待另一个线程运行结束

package corelesson5;
​
public class ThreadDemo7 {
    public static void main(String[] args) {
        MyThread2 thread2=new MyThread2();
        thread2.start();
        try {
            thread2.join();//主线程等待thread2 线程运行结束之后才运行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i <10 ; i++) {
            System.out.println("hello");
        }
    }
}
class MyThread2 extends  Thread{
​
    @Override
    public void run() {
        for (int i = 0; i <=10 ; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
        }
    }
}

Thread.yield() 主动放弃CPU把机会放给别的线程,然后参与竞争 Running-----ready

4,ThreadLocal 类的使用

5,java线程互斥机制

---多线程之间共享数据问题

5.1 同步块

保证每一段代码同时只能被一个线程访问

关键字

synchronized(对象){}

java中每一个对象都是一把锁有且只有一把钥匙

出同步块就会释放锁的钥匙。

package corelesson5;
​
public class ThreadDemo9 {
    public static void main(String[] args) {
        Date date =new Date();
        //数据共享的问题
      Thread t1= new Thread(date);
      Thread t2= new Thread(date);
     t1.start();
     t2.start();
    }
​
}
class Date implements Runnable{
    private  int i;
    @Override
    public void run() {
        int h;
​
        for (int j = 0; j <10 ; j++) {
       synchronized (this){
           h=i+1;
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           i=h;
       }
            System.out.println(i);
​
        }
    }
}
package corelesson5;
​
public class ThreadDemo10 {
    public static void main(String[] args) {
        Date date =new Date();
        //数据共享的问题
      Thread t1= new Thread(date);
      Thread t2= new Thread(date);
     t1.start();
     t2.start();
    }
​
}
​
class Date1 implements Runnable{
    private  int i;
    @Override
    public synchronized void  run() {
        int h;
​
        for (int j = 0; j <10 ; j++) {
​
           h=i+1;
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           i=h;
​
            System.out.println(i);
​
        }
    }
}

5.2 同步函数 也是有锁存在的

--普通方法的锁就是 当前对象

在任何方法 前面都可以加关键字synchronized

静态函数同步块也是有锁的---》 锁是当前类的类类型

注意:多个线程共享数据要保证是同一把锁。

注意:死锁的问题 死锁程序就卡死,无法调试----》可以通过好的工具来检查死锁的问题。

两个线程相互等待对方释放锁。

要慎用synchronized 关键字。

注意:之前我们讲 stringbufferder 和stringbuilder

还有集合ArrayList / Vecter(有关键字synchronized)

5.3 synchronized很繁琐 比较不要理解而且不面向对象

java5 版本做了很好的改进 有了Lock 对象。

大多数情况下用语句。

Lock l=。。。

l.lock().

try{

//程序。。。。。

}finally{

l.unlock().

}

Lock 对象

package corelesson5;

import com.sun.org.apache.xpath.internal.operations.Variable;

import javax.lang.model.element.VariableElement;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadDemo12 {
    public static void main(String[] args) {
      final   Output1 output = new Output1();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    output.print("hello");
                }

            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    output.print("world");
                }

            }
        }).start();
    }
}

class Output1{
    //穿建了锁对象
   Lock lock= new ReentrantLock();
    public void print(String name){
         lock.lock();
         try {
             for (int i = 0; i <name.length() ; i++) {
                 System.out.print(name.charAt(i));
             }
             System.out.println();
         }finally {
             lock.unlock();
         }
    }
}

扩展内容 线程并发下的缓存

package corelesson5;

import java.util.HashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class CacheDemo {
    /**
     * 修改数据的时候 只能一个线程  但是如果只是读数据所有线程可以访问、
     * 读写锁的机制解决这个问题。
     */
    HashMap<String,String >hm=new HashMap<String ,String>();
    private ReentrantReadWriteLock rrw=new ReentrantReadWriteLock();
    private java.lang.String value=null;
    public java.lang.String fetDate(String key){
       /* value=hm.get(key);
        if(value==null){
            value="hello";//将来通过其他资源获取 ,每一次获取value的时候直接从map 中获取
            hm.put(key,value)  ;
        }

        return value;
*/
       rrw.readLock().lock();//进来之后先读数据
        try {
          value=hm.get(key);// 大家都可以来读这个数据
           if(value==null){
               // 要进行写操作
               rrw.readLock().unlock();
               rrw.writeLock().lock();
               try{if(value==null) {
                   value = "hello";
                   hm.put(key, value);
               }
               }finally {
                   rrw.writeLock().unlock();
                   rrw.readLock().lock();

               }
           }
        }finally {
            rrw.readLock().unlock();
        }
        return  value;
    }
 }

6,java线程通讯机制

6.1通过管道流的方式进行通讯

package corelesson5;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class ThreadDemo13 {
    public static void main(String[] args) {
        PipedOutputStream out=null;
        PipedInputStream in=null;
        try {
            in=new PipedInputStream();
            out=new PipedOutputStream(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Sender sender =new Sender(out);
        Thread t1= new Thread(sender);
        Receiver receiver = new Receiver(in);

        Thread t2= new Thread(receiver);
        t1.start();
        t2.start();

    }
}
class Sender implements  Runnable{
  private OutputStream out;
    public Sender(OutputStream out) {
        this.out = out;
    }

    @Override
    public void run() {
        for (int i = 0; i <5 ; i++) {
            byte value =(byte)(Math.random()*100);
            System.out.println("send the value is :"+value);
            try {
                out.write(value);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
 class Receiver implements  Runnable{
    private InputStream in;
    public Receiver(InputStream in) {
        this.in = in;
    }
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                byte value=(byte)in.read();
                System.out.println("receiver the value is "+value);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

通过 管道进行简单的通讯,(性能较差)

6.2 通过 Thread.yield() 方式

yield(一直放弃cpu资源等待)

模拟生产者 和消费者的模型

package corelesson5;

import java.util.Random;

public class ThreadDemo14 {

    public static void main(String[] args) {

        FlagSend flagSend = new FlagSend();
        FlagRec flagRec = new FlagRec(flagSend);
     Thread t1=new Thread(flagSend);
     Thread t2=new Thread(flagRec);
      t1.start();
      t2.start();
    }


}

class FlagSend implements Runnable{
    int theValue;
    boolean flag;



    @Override
    public void run() {
        for (int i = 0; i <5 ; i++) {
            while (flag){
                Thread.yield();
            }
             theValue= new Random().nextInt(1000);// 制造食物
            System.out.println("send the value is :"+ theValue);

            // 自己去等待 让食客去吃
            flag=true;
        }
    }
}

class FlagRec implements Runnable{
    private FlagSend flagSend;

    public FlagRec(FlagSend flagSend) {
        this.flagSend = flagSend;
    }
    @Override
    public void run() {
        for (int i = 0; i <5 ; i++) {
            while (!flagSend.flag){
                Thread.yield();
            }
            System.out.println("receiver the value is :"+flagSend.theValue);
            flagSend.flag=false;



        }
    }
}

效率也比较差 。yield 是放弃了cup 然后又去死循环的竞争 放弃,给CPU 会造成很大的压力。

6.3线程间通讯 wait/notify 方式来通讯 ,等待 和唤醒其他线程。

概念: 任何一个对象 都拥有一个线程等待池,挂在同一个对象的线程等待池中的线程之间可以互相唤醒。

所以 wait/notify 方法是属于object 类的。

wait 方法的使用必须放在synchronized 同步块中。

package corelesson5;

import java.util.Random;

public class ThreadDemo15 {
    public static void main(String[] args) {
        WaitSeed send = new WaitSeed();
        waitRec rec = new waitRec(send);

        Thread t1 = new Thread(send);
        Thread t2 = new Thread(rec);
        // 把t2 线程设置为守护线程,当只有守护线程运行的时候程序自动结束
        t2.setDaemon(true);
        t1.start();
        t2.start();
    }
    
}
class WaitSeed implements  Runnable{

boolean flag;
int theValue;
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
           synchronized (this){
               while (flag){
                   //  为什么 需要用while 存在中断和虚假唤醒
                   try {
                       this.wait();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
               //  生产者生产食物
               theValue= new Random().nextInt(1000);
               System.out.println("send the value is:"+theValue);
               // 自己去等待
               flag= true;
               //唤醒消费者
               this.notify();
           }

        }
    }


}
class  waitRec implements  Runnable{
    // 把生产者作为你的成员

    private WaitSeed send;

    public waitRec(WaitSeed send) {
        this.send = send;
    }

    @Override
    public void run() {
        // 不知道生产者生产多少食物,生产多少消费多少
        while(true)
        {
            synchronized (this){
                while (!send.flag){
                    try {
                        send.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();

                    }
                }
                //  不等待的话 就消费食物
                System.out.println( "receiver the value is :"+send.theValue);
                send.flag=false;
                send.notify();
            }
        }

    }
}

面试题:

先A线程运行10次, 然后B线程运行20次

如此反复50次

理解:A线程生产者, 生产食物需要循环10次,

B线程是消费者 消费食物循环20 次,

package corelesson5;

public class ThreadDemo18 {

    public static void main(String[] args) {
      final Business1 bus = new Business1();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    bus.a();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    bus.b();
                }
            }
        }).start();

    }
}
class Business1{
    boolean flag;
    public void a(){
        synchronized (this){
            while(flag){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("A线程循环"+i);

            }
            flag=true;
            this.notify();
        }

    }


    public void b(){
   // B是消费者
        synchronized (this){
   while(!flag){
       try {
           this.wait();
       } catch (InterruptedException e) {
           e.printStackTrace();

       }
   }

   //循环20次
            for (int i = 0; i < 20; i++) {
                System.out.println("B 线程循环"+i);

            }
            flag=false;
            this.notify();

        }
    }

}

6.4 java 中引入了新的线程通讯方式(了解)

用的是锁机制

7,线程范围内数据共享

模拟一个缓存map ,每次都从map 中取,没有就往里面放数据。

HashMap<Thread,Object> key,就是当前线程的对象 value 就是你要的数据,不管经过那个模块 就可以先去map 中取。

Thread.currentThread() 获取当前线程对象

package corelesson5;

import java.util.HashMap;
import java.util.Random;

public class ThreadDemo20 {
 private static HashMap<Thread,Integer> data =  new HashMap<>();
    public static void main(String[] args) {
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
              int value= new Random().nextInt(10000);
               data.put(Thread.currentThread(),value);

                    A a = new A();
                    a.getDate();
                    B b = new B();
                    b.getDate();
                    C c = new C();
                    c.getDate();


                }
            }).start();
        }
    }
   static class A{
        public void getDate(){
           Thread t =Thread.currentThread();
           int value =data.get(t);
            System.out.println(t.getName()+" from A get data is:"+value);
        }
    }
    static class B {
      public void getDate(){
          Thread t =Thread.currentThread();
          int value =data.get(t);
          System.out.println(t.getName()+" from B get data is:"+value);

      }

    }
    static class C{
        public void getDate(){
            Thread t =Thread.currentThread();
            int value =data.get(t);
            System.out.println(t.getName()+" from C get data is:"+value);
        }
    }

}

java 中 提供了ThreadLocal 这个类,已经完成了类似的功能,可以直接使用。

package corelesson5;

import java.util.HashMap;
import java.util.Random;

public class ThreadDemo20 {
 private static HashMap<Thread,Integer> data =  new HashMap<>();
  private static ThreadLocal<Integer> tl=new ThreadLocal<>();

    public static void main(String[] args) {
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
              int value= new Random().nextInt(10000);
               data.put(Thread.currentThread(),value);
               tl.set(value);

                    System.out.println("put to "+Thread.currentThread().getName() +"is:"+ value +"    set tl value is:"+value);

                    A a = new A();
                    a.getDate();
                    B b = new B();
                    b.getDate();
                    C c = new C();
                    c.getDate();


                }
            }).start();
        }
    }
   static class A{
        public void getDate(){
           Thread t =Thread.currentThread();
           int value =data.get(t);
            System.out.println(t.getName()+" from A get data is:"+value  +".........threadlocal is:"+tl.get());
        }
    }
    static class B {
      public void getDate(){
          Thread t =Thread.currentThread();
          int value =data.get(t);
          System.out.println(t.getName()+" from B get data is:"+value+".........threadlocal is:"+tl.get());

      }

    }
    static class C{
        public void getDate(){
            Thread t =Thread.currentThread();
            int value =data.get(t);
            System.out.println(t.getName()+" from C get data is:"+value+".........threadlocal is:"+tl.get());
        }
    }

}

主要 用两个方法 tl.set() 放数据 tl.get() 取数据 tl.remove(); 删除。

7.3 写一个类,使得该类砸创建对象时,创建完成之后直接就是同一个线程,同一个对象,不同线程,对象不同。

package corelesson5;

class ThreadDemo21{
    public static void main(String[] args) {
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    UserService us=UserService.getInstance();
                    A a = new A();
                    B b = new B();
                    a.print();
                    b.print();
                }
            }).start();
        }


    }
    static class A{
        public  void print(){
            System.out.println("from A==="+Thread.currentThread().getName());
            UserService us =UserService.getInstance();
            System.out.println("from A==="+Thread.currentThread().getName()+"..A..."+us);


        }
    }
    static class B{
        public  void print(){
            System.out.println("from B==="+Thread.currentThread().getName());
            UserService us =UserService.getInstance();
            System.out.println("from B==="+Thread.currentThread().getName()+"..B..."+us);


        }
    }


}

public class UserService {



    private static ThreadLocal<UserService> tl=new ThreadLocal<>();
    private UserService(){}// 线程私有 ,不然别人一new  就是一个对象

  public static UserService getInstance(){
         UserService us=tl.get();
         if(us==null){
             us= new UserService();
             tl.set(us);
         }
         return us;
  }// 构造函数私有的时候 我们就需要通过静态的方法来返回类的对象。

}

不管是单例模式 还是这种情况,我们都是的构造函数peivate

package corelesson5;

import java.lang.reflect.Constructor;

class ThreadDemo21{
    public static void main(String[] args) {
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    UserService us=UserService.getInstance();
                    A a = new A();
                    B b = new B();
                    a.print();
                    b.print();
                }
            }).start();

        }
        /* 通过反射创建对象,反射可以使得他无效*/
        System.out.println("===================================");
        Class c= UserService.class;
        try {
            Constructor<UserService>cs=c.getDeclaredConstructor(new Class[]{});// 获得自己声明的构造函数
            cs.setAccessible(true);//private 设置访问方式
            UserService us1=cs.newInstance(new Object[]{});
            UserService us2=cs.newInstance(new Object[]{});
            System.out.println(us1=us2);// 看看是不是同一个

        } catch (Exception e) {
            e.printStackTrace();
        }




    }
    static class A{
        public  void print(){
            System.out.println("from A==="+Thread.currentThread().getName());
            UserService us =UserService.getInstance();
            System.out.println("from A==="+Thread.currentThread().getName()+"..A..."+us);


        }
    }
    static class B{
        public  void print(){
            System.out.println("from B==="+Thread.currentThread().getName());
            UserService us =UserService.getInstance();
            System.out.println("from B==="+Thread.currentThread().getName()+"..B..."+us);


        }
    }


}

public class UserService {



    private static ThreadLocal<UserService> tl=new ThreadLocal<>();
    private UserService(){}// 线程私有 ,不然别人一new  就是一个对象

  public static UserService getInstance(){
         UserService us=tl.get();
         if(us==null){
             us= new UserService();
             tl.set(us);
         }
         return us;
  }// 构造函数私有的时候 我们就需要通过静态的方法来返回类的对象。

}

8,java线程池

线程并不是越多越好,如果无限制的穿建线程, 那么线程的创建和销毁都有很大的消耗,

希望 不管执行多少任务,都用固定的线程数来执行

package corelesson5;

public class ThreadDemo22 {

    public static void main(String[] args) {
        /** 创建了10 个线程 执行了10 个任务
         * 不希望有无休止的线程
         * 不管有多少个任务,都让固定的线程来执行
         *  可以让一个线程执行多个任务。
          */

        for (int i = 1; i <=10; i++) {
            final int task=i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("任务"+task);
                }
            }).start();
        }
    }
}

线程池也是java5 之后引入的

如何创建线程池?

Executors 类

newFixedThreadPool() 穿建固定线程数的线程池

newSingleThreadExecutor();// 创建了单一线程,线程只有一个线程。
newCachedThreadPool();//默认创建线程,这些线程会被缓存起来,自动判断要不要创建新的线程
package corelesson5;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadDemo23 {
    public static void main(String[] args) {
        // 创建一个线程池,下面是3个线程并发处理了10 个任务
        ExecutorService threadPool= Executors.newFixedThreadPool(3);// 创建3个固定的线程
        for (int i = 0; i < 10; i++) {// 创建了10个runnable 的实例 都是用同一个线程池的对象threadPool 来执行的
            final  int task=i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 10; j++) {
                        // 每个任务循环10次。
                        System.out.println(Thread.currentThread().getName()+"执行第"+task+"个任务的第:"+j+"次循环");
                    }

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

    }

}

穿建线程池方式二

newCachedThreadPool();//默认创建线程,这些线程会被缓存起来,自动判断要不要创建新的线程

newSingleThreadExecutor();// 创建了单一线程,线程只有一个线程。

newFixedThreadPool() 穿建固定线程数的线程池

newScheduledThreadPool(1)

package corelesson5;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadDemo23 {
    public static void main(String[] args) {
        // 创建一个线程池,下面是3个线程并发处理了10 个任务
        // ExecutorService threadPool= Executors.newFixedThreadPool(3);// 创建3个固定的线程



       // ExecutorService threadPool=Executors.newSingleThreadExecutor();// 创建了单一线程,线程只有一个线程。

        ExecutorService threadPool=Executors.newCachedThreadPool();//默认创建线程,这些线程会被缓存起来,自动判断要不要创建新的线程
      
        for (int i = 0; i < 10; i++) {// 创建了10个runnable 的实例 都是用同一个线程池的对象threadPool 来执行的
            final  int task=i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 10; j++) {
                        // 每个任务循环10次。
                        System.out.println(Thread.currentThread().getName()+"执行第"+task+"个任务的第:"+j+"次循环");
                    }

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

    }

}

package corelesson5;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreadDemo24 {

    public static void main(String[] args) {
        ScheduledExecutorService threadPool= Executors.newScheduledThreadPool(1);
        /** 4 个参数
         * 1,执行什么任务
         * 2 首次执行的延迟时间,
         * 3 连续执行的周期
         * 4, 参数的时间单位
         *
         */
        threadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println(" 爆炸了。。。。");
            }
        },0,2, TimeUnit.SECONDS);

    }
}

8,Callable

Callable 有返回值,

package corelesson5;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ThreadDemo25 {
    public static void main(String[] args) {
        /**前面执行任务都是run 方法执行任务,而run 方法是没有返回值的。
         *  在多线程并发的时候 我们不知道线程什么时候结束
         *  如果线程执行完了能够返回一个值,那么我们就知道线程运行结束了。
         *
         */
        ExecutorService threadPool= Executors.newSingleThreadExecutor();
        //Callable<T> 泛型的具体类型就是返回值的类型 也决定了 Future 泛型的类型
        Future<Integer> future = threadPool.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {

                    System.out.println("线程任务开始。。。。");
                    Thread.sleep(3000);
                System.out.println("线程任务结束。。。。");
                return 10;
            }
        });
        try {
            int value= future.get();// 取返回值
            System.out.println(value);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

关于线程基础内容 就先了解这么多。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值