Java

Java基础知识复盘-多线程

2019-05-06  本文已影响52人  Waldeinsamkeit4

一、Java基础知识复盘-多线程

1.1.线程的创建和使用

方式一:继承Thread类

public class ThreadTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        for (int i = 0; i < 1000; i++) {
            if (i % 2 == 0) {
                System.out.println("我是主线程,求偶数:" + i);
            }
        }
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            if (i % 2 != 0) {
                System.out.println("我是子线程,求奇数:" + i);
            }
        }
    }
}

方式二:实现Runnable接口

public class RunnableTest {
    public static void main(String[] args) {
        MyRunnableThread myRunnableThread = new MyRunnableThread();
        Thread thread = new Thread(myRunnableThread);
        thread.start();
    }
}

class MyRunnableThread implements Runnable {
    @Override
    public void run() {
        Thread.currentThread().setName("子线程");
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

方式三:实现Callable接口

public class CallableTest {
    public static void main(String[] args) {
        CallableThread callableThread = new CallableThread();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(callableThread);
        new Thread(futureTask).start();
        try {
            Integer sum = futureTask.get();
            System.out.println(sum);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class CallableThread implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 1000; i++) {
            sum += i;
        }
        return sum;
    }
}

对比方式二,有什么不同

方式四:使用线程池

public class ThreadPoolTest {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        Future submit = executorService.submit(new MyThreadPool());
    }
}

class MyThreadPool implements Callable {

    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
            sum += i;
        }
        return sum;
    }
}

说明:

ExecutorService是真正的线程池接口,常见的子类有ThreadPoolExcutor

Executors是一个工具类,用于创建不同的线程池,如下

尴尬的是,线程池不建议使用Executors去创建,而是通过ThreadPoolExecutor的方式。如下所示:

public class ThreadPoolFactoryTest {
    private static ThreadFactory myThreadFactory = new ThreadFactoryBuilder().setNameFormat("Mythread-pool-%d").build();

    private static ThreadPoolExecutor myThreadPool = new ThreadPoolExecutor(10, 30, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(), myThreadFactory);

    public static void main(String[] args) {
        myThreadPool.execute(new MyThread2());
    }
}

class MyThread2 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

Thread类的常用方法

1.2.线程的生命周期

线程的生命周期状态定义在Thread.State枚举类中,NEWRUNNABLEBLOCKEDWAITINGTIMED_WAITING``TERMINATED。简单的将一个线程的状态有:新建、就绪、运行、阻塞和死亡五种状态。

生命周期图解

image-20190402234652085

1.3.线程的同步

线程的同步就是为类解决线程安全问题,线程安全问题就是程序在单线程和多线程分别执行后,结果不一样。这就出现了线程不安全。

synchronized关键字

使用synchronized关键字,同步代码块,将操作共享数据的代码放在同步代码块中,共享数据就是指多个线程共同操作的变量。同步监视器就是锁,任何一个类的对象都可以充当锁,要求多个线程共用同一把锁。语法如下:

synchronized (同步监视器){

}
public class ThreadState {
    public static void main(String[] args) {
        TicketThread ticketThread1 = new TicketThread();
        Thread thread1 = new Thread(ticketThread1);
        thread1.setName("窗口一");
        thread1.start();
        Thread thread2 = new Thread(ticketThread1);
        thread2.setName("窗口二");
        thread2.start();
        Thread thread3 = new Thread(ticketThread1);
        thread3.setName("窗口三");
        thread3.start();
    }
}

class TicketThread implements Runnable {

    private int ticket = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (this ) {
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + ":买票,票号:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

1.4.线程的通信

上一篇 下一篇

猜你喜欢

热点阅读