java线程与线程安全的单例模式

四种使用线程的方式:继承Thread、实现Runnable接口、实现Callable接口、使用线程池(ThreadPool);代码:

package com.jay.contact;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.locks.ReentrantLock;

//视频教程 https://www.bilibili.com/video/BV1Kb411W75N?p=436
public class ThreadTest {
    public static void main(String[] args) {
        // 方式一 继承 Thread 类
//        ThreadTest1 t1 = new ThreadTest1(123);
//        t1.setPriority(Thread.MAX_PRIORITY);
//        t1.start();

        // 方式二 实现 Runnable 接口
//        ThreadTest2 t2 = new ThreadTest2(666);
//        new Thread(t2).start();

        // 加锁 实现线程同步
//        ThreadTest3 t3_1 = new ThreadTest3();
//        
//        Thread t1 = new Thread(t3_1);
//        t1.setName("ticket1");
//        t1.start();
//
//        Thread t2 = new Thread(t3_1);
//        t2.setName("ticket2");
//        t2.start();

        // 同步方法 实现线程同步
//        ThreadTest4 t4_1 = new ThreadTest4();
//
//        Thread t1 = new Thread(t4_1);
//        t1.setName("ticket1");
//        t1.start();
//
//        Thread t2 = new Thread(t4_1);
//        t2.setName("ticket2");
//        t2.start();

        // 线程安全 ReentrantLock 加锁 实现线程同步
//        ThreadTest5 t5_1 = new ThreadTest5();
//
//        Thread t1 = new Thread(t5_1);
//        t1.setName("ticket1");
//        t1.start();
//
//        Thread t2 = new Thread(t5_1);
//        t2.setName("ticket2");
//        t2.start();

        // 方法三 实现 Callable 接口
//        ThreadTest6 tt6 = new ThreadTest6();
//        FutureTask<Integer> fTask = new FutureTask<Integer>(tt6);
//        new Thread(fTask).start();
//        try {
//            // get()返回的是ThreadTest6的call()返回的sum
//            Integer obj = fTask.get();
//            System.out.println("sum:" + obj);
//        } catch (InterruptedException e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        } catch (ExecutionException e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        }
        
        //方法四 使用线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
      ThreadPoolExecutor s1 = (ThreadPoolExecutor)service;
      s1.setCorePoolSize(10);
      s1.setKeepAliveTime(1, TimeUnit.HOURS);
      s1.setMaximumPoolSize(30);
        s1.execute(new ThreadTest2());//适用于实现 Runnable 接口的类
        s1.submit(new ThreadTest6());//适用于实现 Callable 接口的类
        s1.shutdown();//关闭线程池
    }
}

/**
 * 1.创建一个继承Thread的子类 2.重写Thread的run(),将要执行的操作写在run()里面 3.创建子类的对象 4.调用子对象的start()
 */
class ThreadTest1 extends Thread {
    public ThreadTest1() {
    }

    public ThreadTest1(int number) {
        super();
        this.number = number;
    }

    public int number;

    @Override
    public void run() {
        String tName = Thread.currentThread().getName();
        System.out.println(tName + "/" + number);
    }
}

class ThreadTest2 implements Runnable {
    public ThreadTest2() {
    }

    public ThreadTest2(int number) {
        super();
        this.number = number;
    }

    public int number;

    @Override
    public void run() {
        String tName = Thread.currentThread().getName();
        System.out.println(tName + "/" + number);
    }
}

/*
 * 线程安全 synchronized 加锁 实现线程同步
 */
class ThreadTest3 implements Runnable {
    private static final Object objLock = new Object();
    public static int number = 100;

    @Override
    public void run() {
        while (true) {
            // 创建多个 ThreadTest3 对象时,使用 objLock/this.getClass()/ThreadTest3.class 当锁
            // 创建一个 ThreadTest3 对象,多个 Thread 使用该对象时,可以使用 this 当锁,尽量不要使用this锁
//            synchronized (objLock) {
            synchronized (this.getClass()) {
//            synchronized (ThreadTest3.class) {
//            synchronized (this) {
                if (number > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    String tName = Thread.currentThread().getName();
                    System.out.println("线程:" + tName + "售票:" + number);
                    number--;
                } else {
                    break;
                }
            }
        }
    }
}

/*
 * 线程安全 synchronized 同步方法 实现线程同步
 */
class ThreadTest4 implements Runnable {
    public static int number = 100;

    @Override
    public void run() {
        while (true) {
            boolean res = show();
            if (!res) {
                break;
            }
        }
    }

    // 使用 static synchronized修饰,同步监视器是 ThreadTest4.class,
    // 不加 static,同步监视器是 this,当new多个对象的时候会出错
    public static synchronized boolean show() {
        if (number > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String tName = Thread.currentThread().getName();
            System.out.println("线程:" + tName + "售票:" + number);
            number--;
        }
        return number > 0;
    }
}

/*
 * 线程安全 ReentrantLock 加锁 实现线程同步
 */
class ThreadTest5 implements Runnable {
    public static int number = 100;
    private static ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            boolean res = show();
            if (!res) {
                break;
            }
        }
    }

    public static boolean show() {
        try {
            lock.lock();
            if (number > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String tName = Thread.currentThread().getName();
                System.out.println("线程:" + tName + "售票:" + number);
                number--;
            }
            return number > 0;
        } finally {
            lock.unlock();
        }
    }
}
/*
 * Callable
 * */
class ThreadTest6 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }
}

// 单例模式
class SingletonModel {
    // 私有构造函数,禁止外部new
    private SingletonModel() {
    }

    // 线程安全的饿汉式单例模式
//    public static final SingletonModel instance1 = new SingletonModel();

    // 线程安全的懒汉式单例模式
    private static SingletonModel instance = null;

    public static SingletonModel getInstance() {
        if (instance == null) {
            synchronized (SingletonModel.class) {
                if (instance == null) {
                    instance = new SingletonModel();
                }
            }
        }
        return instance;
    }
}

join:阻塞当前线程,执行完join进来的线程后再继续当前线程。设置线程优先级:getPriority、setPriority,取值Thread.MAX_PRIORITY=10;使用ReentrantLock灵活加锁,实现线程同步
线程通信:
wait() 当前线程进入阻塞状态,并释放同步监视器。
notify() 会唤醒被wait()的线程,如果有多个,则唤醒优先级高的线程。
notifyAll 会唤醒所有被wait()的线程。
这三个只能用在同步方法和同步代码块中,不能放在ReentrantLock中,并且这三个方法的调用者必须是同步代码块或同步方法中的同步监视器。
例如:synchronized(this){...},则 this.notify(),synchronized(obj){...},则 obj.notify()
线程池优点:提高响应速度,减少创建新线程的时间;降低资源消耗,重复使用线程池中的线程,不必每次都创建;便于线程管理(设置核心池大小,最大线程数,没有任务时线程最多保持多少时间后会终止)
sleep()与wait(),
相同点:一旦执行,都可以使当前线程阻塞。
不同点:Thread类中声明sleep(),Object中声明wait();sleep可在任何场景使用,wait在同步代码块或同步方法中使用;如果两个方法都在同步代码块或同步方法中使用sleep不会释放锁,wait会释放锁。
Thread.yield();线程让步,让cpu重新选择线程来执行,可能还会选择自己。
yield、sleep、suspend都不会释放锁。

原文地址:https://www.cnblogs.com/xsj1989/p/14601888.html