提醒:下文内容仅就总结多线程的创建方式,不考虑线程安全问题,且为了直观,在异常处理方面大量省略

一.程序,进程,线程的基本概念

java 创建多线程类 java如何创建多线程_java 创建多线程类


 这里只要做简单的了解即可,红字部分有印象就行,详细内容在虚拟机部分做具体解释

二.创建多线程的四种方式(以多线程抢票为背景)

①在JDK5.0之前:

//1.创建一个子类继承Thread
    class Mythread extends Thread{
    private static int ticket=100;

    //2.重写run方法
    @Override
    public void run() {
        while (true){
            if(ticket>=1){
                System.out.println(getName()+"抢到票"+ticket);
                ticket--;
            }
            else{
                System.out.println(getName()+"票已售罄");
                break;
                    }
            }

        }
    }

    public class Test1  {
        public static void main(String[] args) {
            
           // 3.实例化子类对象
            Mythread t1= new Mythread();
            Mythread t2= new Mythread();
            t1.setName("线程一");
            t2.setName("线程二");


           // 4.start开启线程
            t1.start();
            t2.start();
        }
    }

总结:继承Thread创建多线程的步骤:
  1.创建一个子类继承Thread
  2.重写run方法
  3.实例化子类对象
  4.start开启线程


//1.创建一个实现Runnable接口的类
    class Mythread implements Runnable{
    private int ticket=100;
    //2.重写run方法
    @Override
    public void run() {
        while (true){
            if(ticket>=1){
                System.out.println(Thread.currentThread().getName()+"抢到票"+ticket);
                ticket--;
            }
            else {
                  System.out.println(Thread.currentThread().getName()+"票已售罄");
                  break;
            }
        }
    }   
}
    public class Test1 {
        public static void main(String[] args) {
            //3.创建一个实现类的对象
            Mythread t= new Mythread();
            /*4.每个线程各自创建一个以实现类对象为参数的Thread  
            类的对象*/
            Thread t1=new Thread(t);
            Thread t2=new Thread(t);
            t1.setName("线程一");
            t2.setName("线程二");
            //5.start开启进程
            t1.start();
            t2.start();
        }
    }

总结:继承Thread创建多线程的步骤:
  1.创建一个实现Runnable接口的类
  2.重写run方法
  3.创建一个实现类的对象
  4.每个线程各自创建一个以实现类对象为参数的Thread类的对象
  5.start开启进程


关于Thead带参构造器的源码:

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

不难发现,其参数必须是Runnable接口实现类的对象

注:相比于继承Thread类,方式二可以直接实现数据共享,方式一需要用static修饰成员变量(这一点在讲同步的时候尤其重要)


②在JDK5.0新增:

//1.创建一个实现Callable接口的类
    class MyThread implements Callable {
        //2.重写call函数(由于多态,Obj的返回值类型可以自动向下转化)
        @Override
        public Object call() throws Exception {
            int sum=0;
            for (int i = 0; i <100 ; i++) {
                if (i % 2 == 0) {
                    sum += i;
                    System.out.println(i);
                }
            }
            return sum;
        }
    }
    public class Test1 {
        public static void main(String[] args) throws InterruptedException, UnknownHostException {
            //3.创建一个实现类的对象
            MyThread myThread=new MyThread();
            //4.创建一个FutureTask的对象,传入Callable实现类的对象
            FutureTask futureTask=new FutureTask(myThread);
            //5.创建一个Thread类的对象传入对象futureTask并start
            new Thread(futureTask).start();

            //6.如果需要返回值,再调用futureTask.get()来取返回值
            try {
                Object sum=futureTask.get();
                System.out.println("总和为"+sum);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

总结:
  1.创建一个实现Callable接口的类
  2.重写call方法
  3.创建一个实现类的对象
  4.创建一个FutureTask的对象,传入Callable实现类的对象
  5.创建一个Thread类的对象传入对象futureTask并start
  6.如果需要call函数的返回值,需要调用future.get()的方法

注:Callable可以简单认为是Runnable的升级版,Callable允许有返回值功能更强大

java 创建多线程类 java如何创建多线程_多线程_02


java 创建多线程类 java如何创建多线程_线程池_03

关于FutureTask构造器的源码解析

java 创建多线程类 java如何创建多线程_java_04


java 创建多线程类 java如何创建多线程_java 创建多线程类_05


不难发现,FutrueTask其实继承了Runnable,所以在Tread实例化的时候可以直接带FutureTask的对象,并且上图中的构造器中对callable进行了回调


java 创建多线程类 java如何创建多线程_多线程_06

//1.创建一个实现Runnable接口的类
    class Mythread implements Runnable {
    private int ticket=100;
    //2.重写run方法
    @Override
    public void run() {
        while (true){
        if(ticket>=1){
            System.out.println(Thread.currentThread().getName()+"票"+ticket);

            ticket--;
        }
        else{
            System.out.println(Thread.currentThread().getName()+"售罄了");
            break;
                }
        }
        }
    }

    public class Test1 {
        public static void main(String[] args) {
            //3.提供指定线程数量的线程池
            ExecutorService service=Executors.newFixedThreadPool(10);
            //service.submit(new Mythread());//适用于Callable
            
    //4.执行指定的线程操作需要提供实现Runnable接口或Callable接口的类
            service.execute(new Mythread());//适用于Runnable
            service.execute(new Mythread());
        //关闭线程池
            service.shutdown();
        }
    }

线程池的好处:

java 创建多线程类 java如何创建多线程_java_07


注:用survice.getClass()可以找到survice的实现类,可以发现是ThreadPoolExxcutor,然后上属的方法要通过强转才能用:

ThreadPoolExxcutor survice1=(ThreadPoolExxcutor) survice;