day30_学习总结

day30_学习总结

多线程实现的两种方式

第一种实现方式:通过继承Thread实现
	步骤:
		定义继承Thread的子类
		重写run()方法
		创建线程
		启动线程

第二种实现方式:通过实现Runnable接口
	步骤:
		定义实现Runnable接口的子实现类
		重写run()方法
		创建资源类对象
		创建线程
		启动线程

方式二中的线程操作的是同一个资源类,资源类是共享的,更符合多线程的理念

静态代理

通过代理角色来完成真是角色的功能
代理角色
目标角色:真实角色

静态代理的特点:代理角色和目标角色都必须实现同一个接口
eg:多线程通过Runnable接口实现多线程的方式就是静态代理
	Thread类为代理角色,实现Runnable接口的子实现类是目标角色
	代理角色中要定义实现接口的对象或者真实角色对象
	代理角色中需要有有参构造方法,参数为接口或者实现接口的类(真实角色对象)

同步机制—解决多线程安全问题

同步代码块
格式:
	synchronized(任意类对象){
		对共享数据的操作;
	}
同步方法:将对共享数据的操作定义为一个方法,并且方法声明上通过synchronized修饰
	权限修饰符 synchronized 返回值类型 方法名(){}
静态同步方法:
	权限修饰符 static synchronized 返回值类型 方法名(){}

对于同步方法,其锁对象是this,当前类对象的地址值引用
对于静态同步方法,锁对象是类字节码文件对象,为类名.class
JDK5以后提供接口Lock,也能够实现锁定操作,比synchronized方法更广泛

通过继承Lock接口的子实现类ReentrantLock创建锁对象
void lock()
	对象名.lock();//获取锁
void.unlock()
	对象名.unlock();//释放锁

注意:
对于Lock这种锁操作,可以配合try...finally...使用,通过finally释放资源
try{
	对象名.lock();//获取锁
	对共享资源的操作
}finally{
	if(对象名!=null){
		对象名.unlock();
	}
}
判断多线程安全的标准?
1>是否为多线程环境
2>是否存在共享数据
3>是否有多条语句对共享数据进行操作

死锁现象

多个线程操作不同的资源对象,使用同步代码块之后,造成多个线程之间相互等待的现象

生产者消费者模式–等待唤醒机制

生产者:不断生成数据
消费者:不断消耗数据
操作的是同一个资源对象

通过Object类中的wait()方法和notify()方法


例如:以下学生,不断定义对象,不断输出对象
public class Student {
    private String name ;
    private int age ;
    public boolean flag ;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

public class SetThread implements Runnable {
    private Student s ;

    public SetThread(Student s){
        this.s = s ;
    }

    private int x = 0 ;
    @Override
    public void run() {
        while(true){
            synchronized (s){
                if(s.flag){
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if(x % 2 == 0){
                    s.setName("路飞");
                    s.setAge(19);
                }else{
                    s.setName("索隆");
                    s.setAge(18);
                }

                s.flag = true ;
                s.notify();
            }
            x++;
        }

    }
}

public class GetThread implements Runnable{
    private Student s ;

    public GetThread(Student s){
        this.s = s ;
    }

    @Override
    public void run() {
        synchronized (s) {
            while (true) {
                if(!s.flag){
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(s.getName() + "---" + s.getAge());
                s.flag = false ;
                s.notify();
            }
        }
    }
}

public class StudentDemo {
    public static void main(String[] args) {

        Student s = new Student() ;

        SetThread st = new SetThread(s) ;
        GetThread gt = new GetThread(s) ;

        Thread t1 = new Thread(st) ;
        Thread t2 = new Thread(gt) ;
        t1.start();
        t2.start();
    }
}

面试题

wait()和notify()为什么不定义在Thread类中,而定义在Object类中?
	wait()和notify()方法都和监视锁有关系,通锁对象有关,而锁对象可以为任意Java类对象,因此,定义在Object类中,任意类对象都可以调用这两个方法
sleep()和wait()方法区别?
	不同点:
		来源不同:
			sleep()定义在Thread类中
			wait()定义在Object类中
		是否会释放锁:
			sleep()方法不会释放锁
			wait()方法在调用时会释放锁,然后通过notify()方法唤醒其他线程
	相同点:都存在异常,需要对异常进行处理
			InterruptedException中断异常
上一篇:crm管理软件系统是什么意思?


下一篇:Java学习day30-Map集合