Javase之多线程(2)

多线程(2)

线程的生命周期

新建:创建线程对象

就绪:有执行资格,没有执行权

运行:有资格运行,有执行权

​ 阻塞:由一些操作让线程处于改状态。没有执行资格,没有执行权,而通过另一些操作激活它,激活后处于就绪状态。

死亡:线程对象变成垃圾,等待回收

多线程的实现方式二

实现Runnable接口

步骤:

​ 1.自定义类实现Runnable接口

​ 2.重写run()方法

​ 3.创建自定义类的对象

​ 4.创建Theard类对象并把步骤3的对象作为参数传递。

class T1 implements Runnable{

    @Override
    public void run() {
        for (int i = 0;i < 100;i++){

            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

public class runabletest {
    public static void main(String[] args) {
        T1 t = new T1();

        //public Thread(Runnable target,String name)
        Thread t1 = new Thread(t,"线程a");
        Thread t2 = new Thread(t,"线程b");

//        Thread t1 = new Thread(t);
//        Thread t2 = new Thread(t);
//        t1.setName("线程1");
//        t2.setName("线程2");
        t1.start();
        t2.start();

    }
}

实现接口的好处

1.可以避免由Java单继承带来的局限性。

2.适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效的分离,较好的体现了面向对象的思想。

线程安全问题

导致线程安全问题产生原因(也是判断程序是否出现线程安全问题的批准)

1.是否是多线程环境

2.是否有共享数据

3.是否有多条语句操作共享数据

解决方案

1和2的问题,是不能改变的。所以我们只能考虑改变3

思想:

​ 把多条语句操作共享数据的代码包装成一个整体,让某个线程执行时,其它线程就不能执行。

解决安全问题方案1

同步代码块

格式:synchronized(对象){需要同步的代码块;}

对象是什么:任意对象

需要同步的代码是那部分:多条语句操作共享数据

synchronized (obj) {
            while (n > 0) {
                try {
                    Thread.sleep(100);
                }catch (Exception e){
                    System.out.println("线程结束");
                }
                System.out.println(Thread.currentThread().getName() + "使用" + ":" + (n--));
            }
        }

注:同步可以解决安全问题的根本原因在对象上。该对象如同锁功能。多个线程必须使用同一把锁。

1.同步代码块的锁对象是任意对象

2.同步方法的格式:把同步关键字synchronized加到方法上

​ 其锁对象是this

public synchronized void show(){
        while (n > 0) {
            try {
                Thread.sleep(100);
            }catch (Exception e){
                System.out.println("线程结束");
            }
            System.out.println(Thread.currentThread().getName() + "使用" + ":" + (n--));
        }
    }

3.静态方法锁对象是类的字节码文件。

同步的特点

前提:多个线程

解决问题时注意:多个对象使用同一把锁。

好处:同步解决了多个线程的安全问题。

弊端:当线程较多时,因为每个线程都会去判断同步的锁,会浪费资源,降低程序运行效率。

如何保证集合是安全的

1.Vector是线程安全的

2.调用Collections中对应的方法

List<String> s = Collections.synchronizedList(new ArrayList<String>());

JDK5以后的Lock

为了直接的表达如何加锁和释放锁,JDK5以后提供了一个新对象Lock

Lock:

​ void lock();获取锁

​ void unlock() ;释放锁

ReentrantLock是Lock的实现类。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class T3 implements Runnable {
    private int n = 100;
    Lock l = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            l.lock();
            if (n>0)
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                System.out.println("线程结束");
            }finally {
                System.out.println(Thread.currentThread().getName() + "使用" + ":" + (n--));
                l.unlock();
            }
        }
    }
}

public class Locktest {
    public static void main(String[] args) {
        T3 t = new T3();

        Thread t1 = new Thread(t,"线程a");
        Thread t2 = new Thread(t,"线程b");
        Thread t3 = new Thread(t,"线程c");
        t1.start();
        t2.start();
        t3.start();
    }
}

死锁问题

如果出现同步嵌套,就容易产生死锁问题。

问题描述

指在两个或两个以上的线程在执行过程中,因争夺资源而产生的一种相互等待的现象。

代码

class MyLock{
    static Object objA = new Object();
    static Object objB = new Object();
}

class MyTheard extends Thread{
    boolean flag;

    public MyTheard(boolean flag){
        this.flag = flag;
    }
    public void run(){
        if (flag){
            synchronized (MyLock.objA){
                System.out.println("if objA");
                synchronized (MyLock.objB){
                    System.out.println("if objB");
                }
            }
        }else {
            synchronized (MyLock.objB){
                System.out.println("else objB");
                synchronized (MyLock.objA){
                    System.out.println("else objA");
                }
            }
        }
    }

}

public class Dielocktest {
    public static void main(String[] args) {
        MyTheard m1 = new MyTheard(true);
        MyTheard m2 = new MyTheard(false);

        m1.start();
        m2.start();
    }
}
原文地址:https://www.cnblogs.com/wf614/p/11673843.html