javaseday12(线程,同步代码块 函数,线程安全,死锁)

来源:互联网 发布:sql select语句例子 编辑:程序博客网 时间:2024/06/03 18:12


sleep(time)必须指定睡眠时间 单位是毫秒到点自动唤醒

CPU的执行资格:可以被cpu处理 在处理队列中排队

CPU的执行权:正在被CPU处理


一个特殊的状态 :就绪(临时阻塞) 具备了执行的资格但是还没有获取资源(执行权)


创建线程的第一种方式:继承Thread类 cpu快速切换 导致线程切换

Thread 中有封装线程任务的方法

将自己的方法放在子类的run()中

创建线程的第二种方式:实现Runnable接口

1、定义类实现Runnable接口

2、覆盖接口中的run方法 将线程的任务代码封装到run方法中

3、通过Thread类创建线程对象,并将Runnable接口的子类对象作为构造函数的参数进行传递

因为线程的任务都封装在Runnable接口子类对象的run方法中 所以要在线程对象创建时就必须明确要运行的任务

4、调用线程对象的start方法开启线程


实现Runnable 接口的好处(区别):

1、将线程的任务从线程的子类中分离出来,进行了单独的封装

按照面向对象的思想将任务封装成对象

2、避免了java单继承的局限性

所以创建线程的第二种方式较为常见

子类已经继承了一个fu 可以用接口来扩展功能 让其中的内容作为线程的任务执行

因为不是Thread的儿子

所以要通过

Demo d = new Demo();

Thread t1 = new Thread (d);

Thread(Runnable target)

分配一个新的 Thread对象
简化:
class Thread{

private Runnable r;

Thread(){}

Thread(Runnable r){

this.r=r;

}

public void run(){ //继承的时候该方法被 覆盖 接口的时候通过构造函数 传进去r  然后通过start 调用该方法

if(r!=null)

r.run();

}

public void start(){

run();

}

}

Runnable 仅仅是将线程的任务进行了对象的封装 而不需要继承Thread

Thread 的 run 也来自Runnable 不过做了一个默认的实现

用静态限制具有局限性 (有2个100张票要卖)

1个线程不能启动多次 算是在主线程异常 在主函数内的是主线程异常 run里面的才是其他线程异常

Ticket t = new Ticket(); //创建一个线程任务对象 通过Runnable接口

 Thread t = new Thread(t);

Thread t1 = new Thread(t);

Thread t2= new Thread(t);

Thread t3= new Thread(t);

t.start();
t1.start();
t2.start();
t3.start();

线程安全问题产生的原因:
1、多个线程在操作共享的数据
2、操作共享数据的线程代码有多条


当一个线程在执行操作共享数据的多条代码过程中 其他线程参与了运算
就会导致线程安全问题的产生 

解决思路
就是将多条操作共享数据的线程代码封装起来 当有线程在执行这些代码的时候
其他线程不可以参与运算 必须要当前线程把这些代码都执行完毕后 其他线程才能参与运算

在java中用同步代码块来解决这个问题
同步代码块的格式
synchronized(对象){   不是真实存在实际叫锁(初始为1 线程进来看到1后进来改为0 出去改为1)
需要被同步的代码;
}
同步的好处:解决线程安全的问题 
同步的弊端: 相对降低效率 因为执行权会不断切换 有无效判断(因为同步外的线程都会判断同步锁)

同步的前提: 同步中必须有多个线程并使用同一个锁  注意同一个锁

在函数上加上修饰符 synchronizd  同步函数 
public void run(){
while(true){
show();
}
}

public synchronized void show(){
if(){}
}
同步函数 的锁是this  通过同步代码块 和同步函数 然后 flag = true  执行 同步函数  flag = flase 执行同步代码块来验证
同步函数和同步代码块的区别
同步函数的锁是固定的this
同步代码块的锁是任意的对象

建议使用同步代码块  同步函数是同步代码块的简写  虽然简化 但是唯一锁
静态的函数 的锁是this.getClass() 字节码对象 也可以用类名.class

多线程下的单例
饿汉式 先创建 对象
懒汉式 有需求再创建 有线程安全问题 可以在函数加synchronized 但是降低 了效率 所以在代码块加synchronized(Single.class)
不能加getclass() 因为getclass 是非静态的 
public static Singele getInstance(){
if(s==null){ //解决效率问题
synchronized(Single.class){
if(s==null)//解决线程安全问题
s= new Single();
}
}
return s;
}


死锁:常见情景之一:同步嵌套
Test implements Runnable
private boolean flag;
Test(boolean flag){
this.flag = flag;
}
public void run(){
if(flag){
while(true){
synchronized(MyLock.locka){
syso
synchronized(Mylock.lockb){
syso
}
}
}
}
else{
while(true){
synchronized(MyLock.locka){
syso
synchronized(Mylock.lockb){
syso
}
}
}
}
}
class MyLock{
public static final Object locka = new Object();
public static final Object lockb = newObject();
}
//构造函数和构造代码块的死锁
 public static void main(String[] args) {
Demo r = new Demo();
Thread t = new Thread(r);
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
Thread t3 = new Thread(r);

t.start();
t1.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
r.flag = false;
t2.start();
t3.start();


}
}
class Demo implements Runnable{
private  int num = 100;
boolean flag = true;
Object obj = new Object();
public void run() {
if (flag) {
while (true) {
synchronized (obj) {
show();
}
}
} else
while (true) {
this.show();
}
}

public synchronized void show() {


synchronized (obj) { //卡在这 一个this 一个 obj


if (num > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "..." + num--);
}
}
}
}



简单点的死锁

public static void main(String[] args) {
Demo r = new Demo(true);
Demo r1 = new Demo(false);
Thread t = new Thread(r);
Thread t1 = new Thread(r1);


t.start();
t1.start();
}
}
class Demo implements Runnable{
boolean flag = true;
Demo(boolean flag){
this.flag = flag;
}
 
public void run() {
if(flag) {
while(true) {
synchronized (MyLock.locka) {
System.out.println(Thread.currentThread().getName()+"if locka");
synchronized(MyLock.lockb) {
System.out.println(Thread.currentThread().getName()+"if lock b");
}
}
}
}
else {
while(true) {
synchronized (MyLock.lockb) {
System.out.println(Thread.currentThread().getName()+" else lockb");
synchronized(MyLock.locka) {
System.out.println(Thread.currentThread().getName()+" else locka");
}
}
}
}
}
}
class MyLock {
public static final Object locka = new Object();
public static final Object lockb = new Object();
}














原创粉丝点击