您现在的位置是:主页 > news > 品牌策划是做什么/seo收费

品牌策划是做什么/seo收费

admin2025/5/9 23:07:28news

简介品牌策划是做什么,seo收费,蒲城做网站,如何在百度推广网站目录 第一章 多线程 1.1 线程安全 1.2 线程同步(线程安全处理Synchronized) 1.2.1 同步代码块 1.2.2 同步方法(建议使用) 1.3 Lock接口 1.4 死锁 1.5 等待唤醒机制 第二章 总结 第一章 多线程 1.1 线程安全 如果有多个…

品牌策划是做什么,seo收费,蒲城做网站,如何在百度推广网站目录 第一章 多线程 1.1 线程安全 1.2 线程同步(线程安全处理Synchronized) 1.2.1 同步代码块 1.2.2 同步方法(建议使用) 1.3 Lock接口 1.4 死锁 1.5 等待唤醒机制 第二章 总结 第一章 多线程 1.1 线程安全 如果有多个…

目录

第一章 多线程

1.1 线程安全

1.2 线程同步(线程安全处理Synchronized)

1.2.1 同步代码块

1.2.2 同步方法(建议使用)

1.3 Lock接口

1.4 死锁

1.5  等待唤醒机制

第二章 总结


第一章 多线程

1.1 线程安全

如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

 我们通过一个案例,演示线程的安全问题:

我们来模拟电影院的售票窗口,实现多个窗口同时卖 “功夫熊猫3”这场电影票(多个窗口一起卖这100张票)

需要窗口,采用线程对象来模拟;需要票,Runnable接口子类来模拟

测试类:

package day27.demo1;/** 多线程并发访问同一个数据资源* 3个线程,对一个票资源,出售*/
public class ThreadDemo {public static void main(String[] args) {//创建Runnable接口实现类对象Tickets t = new Tickets();//创建3个Thread类对象,传递Runnable接口实现类Thread t0 = new Thread(t);Thread t1 = new Thread(t);Thread t2 = new Thread(t);t0.start();t1.start();t2.start();}
}

 模拟票:

package day27.demo1;public class Tickets implements Runnable{//定义出售的票源private int ticket = 100;private Object obj = new Object();public void run(){while(true){//对票数判断,大于0,可以出售,变量--操作if( ticket > 0){System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);}}}}

运行结果: 

 

run方法只有一个,但要进栈3次,使用的是同一个票源ticket。假如票剩1张是,t0先抢占了cpu,刚判断完ticket>0,但还未执行ticket--时,cpu被t1抢占,此时ticket依然大于0。此时这种情况会导致最后输出的ticket出现负数。这是线程不安全。

 若我们用休眠来演示cpu被抢占

只需要修改模拟票类:

package day27.demo1;/**  通过线程休眠,出现安全问题*/
public class Tickets implements Runnable{//定义出售的票源private int ticket = 100;private Object obj = new Object();public void run(){while(true){//对票数判断,大于0,可以出售,变量--操作if( ticket > 0){try{Thread.sleep(10);}catch(Exception ex){}System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);}}}}

运行结果:

 

1.2 线程同步(线程安全处理Synchronized)

java中提供了线程同步机制,它能够解决上述的线程安全问题。

线程同步的方式有两种:

方式1:同步代码块

方式2:同步方法

 

1.2.1 同步代码块

同步代码块: 在代码块声明上,加上synchronized。

synchronized (锁对象) {

    可能会产生线程安全问题的代码

}

同步代码块中的锁对象可以是任意的对象;

此对象不能写匿名对象,因为每次while循环,匿名对象就变了,因此必须写有名对象。即多个线程时,要使用同一个锁对象才能够保证线程安全。

使用同步代码块,对电影院卖票案例中Ticket类进行如下代码修改:

package day27.demo1;/**  通过线程休眠,出现安全问题*  解决安全问题,Java程序,提供技术,同步技术*  公式:*    synchronized(任意对象){*      线程要操作的共享数据*    }*    同步代码块*/
public class Tickets implements Runnable{//定义出售的票源private int ticket = 100;private Object obj = new Object();public void run(){while(true){//线程共享数据,保证安全,加入同步代码块synchronized(obj){//对票数判断,大于0,可以出售,变量--操作if( ticket > 0){try{Thread.sleep(10);}catch(Exception ex){}System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);}}}}
}

运行结果:

 

1. 线程遇到同步代码块后,线程判断还有没有同步锁。若有同步锁,则此线程获取锁,进入同步代码块中,去执行代码,执行完毕后,出同步代码块,并且将锁对象还回去。   若没有锁,则此线程被挡在同步代码块的外面。

2. 通过运行我们明显感觉到执行速度变慢。这是因为这是线程安全的,执行速度会变慢。

     因为有了同步之后,线程每次要判断同步锁,获取锁,使用完之后还有释放锁,导致程序运行速度降低。

 

1.2.2 同步方法(建议使用)

同步方法:在方法声明上加上synchronized

比同步代码块好,代码量少。

public synchronized void method(){

   可能会产生线程安全问题的代码

}

同步方法中,锁对象是 this。

	//同步方法中的对象锁,是本类对象引用 thispublic   void payTicket(){//静态方法中的成员也要为静态,因此ticket设为静态synchronized(this) {if( ticket > 0){try{Thread.sleep(10);}catch(Exception ex){}System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);}}
}

静态里面不能写this和super,因为静态是类的共享数据,不属于对象。而this属于对象引用,并且静态优先于非静态存在。

静态的同步方法中,锁对象是本类类名.class。

	//静态方法,同步锁,是本类类名.class属性	public  static void payTicket(){//静态方法中的成员也要为静态,因此ticket设为静态synchronized(Tickets1.class)//与反射有关 {if( ticket > 0){try{Thread.sleep(10);}catch(Exception ex){}System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);}}
}

使用同步方法,对电影院卖票案例中Ticket类进行如下代码修改:

package day27.demo1;/**  采用同步方法形式,解决线程的安全问题*  好处: 代码简洁*  将线程共享数据,和同步,抽取到一个方法中*  在方法的声明上,加入同步关键字*  *  问题:*    同步方法有锁吗,肯定有,同步方法中的对象锁,是本类对象引用 this*    如果方法是静态的呢,同步有锁吗,绝对不是this*    锁是本类自己.class 属性*    静态方法,同步锁,是本类类名.class属性*/
public class Tickets1 implements Runnable{//定义出售的票源private  static int ticket = 100;public void run(){while(true){payTicket();}}public  synchronized void payTicket(){	if( ticket > 0){try{Thread.sleep(10);}catch(Exception ex){}System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);}}//	//静态方法,同步锁,是本类类名.class属性	
//	public  static void payTicket(){
//		
//		//静态方法中的成员也要为静态,因此ticket设为静态
//		synchronized(Tickets1.class)//与反射有关 {
//		if( ticket > 0){
//			try{
//			   Thread.sleep(10);
//			}catch(Exception ex){}
//			System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);
//		}
//		}
//}//	//同步方法中的对象锁,是本类对象引用 this
//	public   void payTicket(){
//		//静态方法中的成员也要为静态,因此ticket设为静态
//		synchronized(this) {
//		if( ticket > 0){
//			try{
//			   Thread.sleep(10);
//			}catch(Exception ex){}
//			System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);
//		}
//		}
//}}

 

1.3 Lock接口

public  synchronized void payTicket(){	if( ticket > 0){try{Thread.sleep(10);}catch(Exception ex){}System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);}}

此代码中,有以下两个问题:

1. 何时获取锁我们知道,但是何时释放锁,我们并不知道。

2.若在sleep过程中,真的发生了异常,catch后此线程执行结束,但是锁没有释放,因为不出同步块,锁不释放。

因此出现了Lock来替换synchronized

Lock实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作。

Lock接口中的常用方法:

 

Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能。

我们使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Ticket类进行如下代码修改:

package day27.demo1;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**  使用JDK1.5 的接口Lock,替换同步代码块,实现线程的安全性*  Lock接口方法:*     lock() 获取锁*     unlock()释放锁*  实现类ReentrantLock*/
public class Tickets_2 implements Runnable{//定义出售的票源private int ticket = 100;//在类的成员位置,创建Lock接口的实现类对象//写在run中不可(若有多个线程,则有多个锁,此应为共享资源),写在while循环中每次循环生成的锁不同。private Lock lock = new ReentrantLock();public void run(){while(true){//调用Lock接口方法lock获取锁lock.lock();//对票数判断,大于0,可以出售,变量--操作if( ticket > 0){try{Thread.sleep(10);System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);}catch(Exception ex){}finally{//释放锁,调用Lock接口方法unlocklock.unlock();}}}}
}

 

1.4 死锁

同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就避免掉。

synchronzied(A锁){

    synchronized(B锁){        

    }

}

外部类要访问非静态成员需要对象调,但是此方法为私有的,外部类不能创建对象。因此外部类可以静态调,不需要对象。

1. 定义锁对象类

package day27.demo1;public class LockA {private LockA(){}public  static final LockA locka = new LockA();
}
package day27.demo1;public class LockB {private LockB(){}public static final LockB lockb = new LockB();
}

 2.线程任务类 

package day27.demo1;public class DeadLock implements Runnable{private int i = 0;public void run(){while(true){//随着循环次数增多,发生死锁的几率就增加了if(i%2==0){//先进入A同步,再进入B同步synchronized(LockA.locka){//外部类不能创建对象,但是外部类可以静态调 LockA.lockaSystem.out.println("if...locka");synchronized(LockB.lockb){System.out.println("if...lockb");}}}else{//先进入B同步,再进入A同步synchronized(LockB.lockb){System.out.println("else...lockb");synchronized(LockA.locka){System.out.println("else...locka");}}}i++;}}
}

3.测试类

package day27.demo1;
public class DeadLockDemo {public static void main(String[] args) {DeadLock dead = new DeadLock();Thread t0 = new Thread(dead);Thread t1 = new Thread(dead);t0.start();t1.start();}
}

运行结果: 

 

1.5  等待唤醒机制

线程之间的通信:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。

通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制

等待唤醒机制所涉及到的方法:

  1. wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。
  2. notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。
  3. notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。

其实,所谓唤醒的意思就是让 线程池中的线程具备执行资格。必须注意的是,这些方法都是在 同步中才有效。同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。

仔细查看JavaAPI之后,发现这些方法 并不定义在 Thread中,也没定义在Runnable接口中,却被定义在了Object类中,为什么这些操作线程的方法定义在Object类中?

因为这些方法在使用时,必须要标明所属的锁,而锁又可以是任意对象。能被任意对象调用的方法一定定义在Object类中。

建在while循环内不对,没次循环,建立不同的Resource对象。 建在run内也不合适,若有三个线程,三个run,每个run都有自己的Resource,不合适。Resource应该为共享数据。

输出null..null的解决方法:

方法一:死锁中的静态调用

方法二:在测试类中创建一个对象,给input和output传参。 

但依然出现问题,lisi性别是nv,但打印出为男。 

性别与名字不匹配的问题,解决方法:写和读都要加锁,都为资源锁,不能为this锁。

需要锁的对象调用wait() 

输入线程任务类:

package day27.demo1;
/**  输入的线程,对资源对象Resource中成员变量赋值*  一次赋值 张三,男*  下一次赋值 lisi,nv*/
public class Input implements Runnable {private Resource r ;public Input(Resource r){this.r = r;}public void run() {int i = 0 ;while(true){synchronized(r){//标记是true,等待if(r.flag){try{r.wait();}catch(Exception ex){}}if(i%2==0){r.name = "张三";r.sex = "男";}else{r.name = "lisi";r.sex = "nv";}//将对方线程唤醒,标记改为truer.flag = true;r.notify();}i++;}}}

输出线程任务类:

package day27.demo1;
/**  输出线程,对资源对象Resource中成员变量,输出值*/
public class Output implements Runnable {private Resource r ;public Output(Resource r){this.r = r;}public void run() {while(true){synchronized(r){	//判断标记,是false,等待if(!r.flag){try{r.wait();}catch(Exception ex){}}System.out.println(r.name+".."+r.sex);//标记改成false,唤醒对方线程r.flag = false;r.notify();}}}}

模拟资源类: 

package day27.demo1;
/**  定义资源类,有2个成员变量*  name,sex*  同时有2个线程,对资源中的变量操作*  1个对name,age赋值*  2个对name,age做变量的输出打印*/
public class Resource {public String name;public String sex;public boolean flag = false;
}

测试类: 

package day27.demo1;
/**  开启输入线程和输出线程,实现赋值和打印值*/
public class ThreadDemo3{public static void main(String[] args) {Resource r = new Resource();Input in = new Input(r);Output out = new Output(r);Thread tin = new Thread(in);Thread tout = new Thread(out);tin.start();tout.start();}
}

运行结果:

 

第二章 总结

同步锁

多个线程想保证线程安全,必须要使用同一个锁对象

同步代码块

         synchronized (锁对象){

    可能产生线程安全问题的代码

}

同步代码块的锁对象可以是任意的对象

同步方法

         public synchronized void method()

              可能产生线程安全问题的代码

}

                           同步方法中的锁对象是 this

 

 

静态同步方法

public synchronized void method()

              可能产生线程安全问题的代码

}

静态同步方法中的锁对象是 类名.class

 

多线程有几种实现方案,分别是哪几种?

         a, 继承Thread类

         b, 实现Runnable接口

         c, 通过线程池,实现Callable接口

 

同步有几种方式,分别是什么?

         a,同步代码块

         b,同步方法

           静态同步方法

为什么wait(),notify(),notifyAll()等方法都定义在Object类中

         锁对象可以是任意类型的对象