Java线程Thread

创建线程的三种方式:

  • 继承Thread:
 private class TestThread extends Thread{
        @Override
        public void run() {
            super.run();
        }
    }
//启动
TestThread testThread = new TestThread();
        testThread.start();
  • 实现Runnable接口
 private class TestThread1 implements Runnable{
        @Override
        public void run() {

        }
    }}
//启动
Thread testThread1 = new Thread(new TestThread1());
        testThread1.start();
  • Callable及FutureTask,获取多线程返回值
 private class TestThread2 implements Callable{
        @Override
        public String call() throws Exception {
            //运行逻辑,并返回结果
            return "a"+"b";
        }
    }
//启动
        Callable testThread2 = new TestThread2();
        FutureTask futureTask = new FutureTask<>(testThread2);
        Thread thread = new Thread(futureTask);
        thread.start();

Thread的常用方法

方法 说明
start() 启动线程
setName(String name) 设置线程名称
setPriority(int priority) 设置线程优先级,默认5,取值1-10,优先级系统之后尽量优先调用并不是优先级高的一定先执行;
join(long millisec) 抢占线程,使用后该线程执行完毕前其他线程不等待;传入时间(毫秒)占用多长时间后其他线程继续可以执行;
interrupt() 终止线程
isAlive() 测试线程是否处于活动状态
Thread静态(static)方法
方法 说明
yield() 暂停当前正在执行的线程对象,并执行其他线程。
sleep(long millisec)/sleep(long millis, int nanos) 挂起线程xx秒,参数不可省略
currentThread() 返回对当前正在执行的线程对象的引用
holdsLock(Object x) 当前线程是否拥有锁

sleep()和wait()的区别

本质的区别是:sleep不释放锁,wait释放锁;
用法上的不同:sleep(milliseconds)可以用时间指定来使他自动醒过来,
如果时间不到只能调用interreput()来终止线程;
wait()可以用notify()/notifyAll()直接唤起。

线程的生命周期状态

线程的状态可以使用getState()查看

状态 描述
NEW 尚未启动
RUNNABLE 正在执行中
BLOCKED 阻塞的(被同步锁或者IO锁阻塞)
WAITING 永久等待状态
TIMED_WAITING 等待指定的时间重新被唤醒的状态
TERMINATED 执行完成

synchronized关键字(线程同步)

synchronized关键字提供了一种锁机制,能确保共享变量的互斥访问,防止数据不一致的问题出现。

  • 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
  • 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
  • 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
  • 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
修饰一个代码块

一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞;

public static void main(String[] args) {
        MyThread myThread = new MyThread();
        //注意引用同一个对象,不要new 2次
        Thread one = new Thread(myThread, "one");
        Thread two = new Thread(myThread, "two");
        one.start();
        two.start();
    }
    private  static int count=0;
    public static class MyThread implements Runnable{
        @Override
        public void run() {
            synchronized (this){
                for (int i = 0; i <5 ; i++) {
                    count=count+1;
                    System.out.print(Thread.currentThread().getName()+"-"+count+",");
                    try {//方便查看执行顺序
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
//执行结果:
one-1,one-2,one-3,one-4,one-5,two-6,two-7,two-8,two-9,two-10,

修饰一个方法

//调用
for (int i = 0; i <5 ; i++) {
            TestThread bank = new TestThread();
            bank.start();
        }
private int count=0;
    private class TestThread extends Thread{
        @Override
        public void run() {
            super.run();
            System.out.println("value="+getValue());
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        private synchronized int getValue(){
            count=count+1;
            return count;
        }
    }
//输出结果:value=1,value=2,value=3,value=4,value=5

指定要给某个对象加锁 (修饰的对象如果是static则加锁的是整个类)

//调用 
 for (int i = 0; i <10 ; i++) {
            Bank bank = new Bank();
            if (i%2==0){
                bank.setName("A");
            }else {
                bank.setName("B");
            }
            bank.start();
        }
 private Object balance=100;
    private class Bank extends Thread{
        @Override
        public void run() {
            super.run();
            synchronized (balance){
                if (getName().equals("A")){
                    Integer balance1= (Integer) balance;
                    balance=balance1+50;
                    System.out.println("存钱:"+balance);
                }else {
                    Integer balance1= (Integer) balance;
                    balance=balance1-50;
                    System.out.println("取钱:"+balance);
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
//输出:存钱:150,取钱:100,取钱:50,取钱:0,取钱:-50,取钱:-100,存钱:-50,存钱:0,存钱:50,存钱:100

线程协作 wait()、notify/notifyAll() 详解

  • wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写。
  • wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 同步代码块里使用 wait()、notify/notifyAll() 方法。
  • 由于 wait()、notify/notifyAll() 在synchronized 代码块执行,说明当前线程一定是获取了锁的;
  • wait() 需要被try catch包围,以便发生异常中断也可以使wait等待的线程唤醒。
  • notify 和wait 的顺序不能错,如果A线程先执行notify方法,B线程在执行wait方法,那么B线程是无法被唤醒的。
 //调用 2个子线程顺序执行,一个执行一次;
        Product product = new Product();
        new addProduct(product).start();
        new subProduct(product).start();
//生产商品
    private class addProduct extends Thread {
        private Product product;

        public addProduct(Product product) {
            this.product = product;
        }
        @Override
        public void run() {
            super.run();
            while (true) {
                product.addProduct();
            }
        }
    }

    //消费商品
    private class subProduct extends Thread {
        private Product product;

        public subProduct(Product product) {
            this.product = product;
        }
        @Override
        public void run() {
            super.run();
            while (true) {
                product.subProduct();
            }
        }
    }
    //商品类
    private class Product {
        private int product = 0;
        private boolean isAdded = false;//通过参数控制协作
        public synchronized void addProduct() {
            if (isAdded) {
                try {
                    wait();//线程等待
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            product = product + 1;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("add-" + product);
            isAdded=true;
            notifyAll();//唤醒所有等待线程
        }
        public synchronized void subProduct() {
            if (!isAdded) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            product = product - 1;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("sub-" + product);
            isAdded=false;
            notifyAll();
        }
    }
//输出结果
add-1
sub-0
add-1
sub-0
add-1
sub-0
add-1
...

你可能感兴趣的:(Java线程Thread)