day11多线程,run方法。卖票多线程示例。synchronized,同步锁对象,回顾单例。死锁问题

/*
多线程,run方法。卖票多线程示例。synchronized,同步锁对象,回顾单例。死锁问题
*/
多线程
	进程和线程的区别。
		每一个正在执行的程序叫进程,一个进程里至少有一个线程。

		多线程存在的意义:让程序同时执行
		多线程的创建方式:
		第一:就是继承Thread类
		1.定义类继承Thread.
		2.覆盖run方法。public void run()
		3.创建对象。new Demo();
		4.调用线程的start()方法。该方法有二个作用。

class Demo extends Thread
{
	public void run()
	{
		for(int x=0;x<60;x++){
			System.out.println("Demo run"+x);
		}
	}
}

class ThreadDemo
{
	public static void main(String[] args)
	{
		Demo d = new Demo();
		d.start();

		for(int x=0;x<60;x++){
			System.out.println("main run"+x);
		}

	}
}

为什么要覆盖run方法?
Thread用于描述线程。该类定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法。
也就是说,Thread 类中的run方法,用于存储线程要运行的代码。
	Thread t = new Thread();t.start();//要覆盖run方法才有意义。

	线程运行的几种状态
		被创建,运行,冻结,消亡状态,阻塞状态。


线程都有自己默认的名字。从0开始,getName()获取。
	通过构造方法super(String name)可以设置。
	Thread.currentThread().getName()===this.getName();
	currentThread():获取当前线程对象,静态的,通过
	getName():获取线程名字。
	设置线程名字:setName()或者构造函数。super();

	class Ticket extends Thread
	{
		private static  int tick = 100;//静态可以解决共享数据
		public void run()
		{
			while (true)
			{
				if (tick>0)
				{
					System.out.println(currentThread().getName()+"sale:"+tick--);
				}
				
			}
		}
	}

	class TicketDemo
	{
		public static void main(String[] args)
		{
			Tictet t1 = new Tictet();
			Tictet t2 = new Tictet();
			Tictet t3 = new Tictet();
			Tictet t4 = new Tictet();
			t1.start();t2.start();
			t3.start();t4.start();
		}
	}

	创建线程的第二种方式,1实现一个Runnable接口。2覆写run()方法。
	3.通过Thread类创建线程对象。4.把实现接口的类对象作为参数传给Thread();
	5.通过Thread类,开启start()。
	class Demo implements Runnable
	{
		public void run()
		{

		}
	}

	new Thread(new Demo()).start();

		



		//卖票程序
	class Ticket implements Runnable//extends Thread
	{
		private int tick = 100;//静态可以解决共享数据
		public void run()
		{
			while (true)
			{
				if (tick>0)
				{
					System.out.println(currentThread().getName()+"sale:"+tick--);
				}
				
			}
		}
	}

	class TicketDemo
	{
		public static void main(String[] args)
		{
			Tictet t = new Ticket();
			new Thread(t).start();
			new Thread(t).start();
			new Thread(t).start();
			new Thread(t).start();
		}
	}

	实现方式和继承方式有什么区别?
	继承具有局限性,因为java是单继承,继承了Thread类就不能继承别的类。
	实现方式的好处在于避免了单继承的局限性,建议使用实现方式。

多线程的安全问题:
	卖票当1>0时,此线程等待,其他线程过来,然后再判断1>0,执行完后,然后此线程再减减,会出现负数情况。
	当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行一部分
	还没有执行完,另一个线程参与进来,导致共享数据的错误。
	解决办法 :对多条操作共享数据的语句,只能让一个线程执行完,在执行过程中,
	其他线程不可以参与执行。

	java对于多线程的安全问题,提供了专业的解决方式。同步代码块。
	synchronized(对象)
	{
		需要被同步的代码
	}
	//这个对象:你想放哪个就放哪个。只要是对象就行。
		synchronized(对象)
		{
			while (true)
			{
				if (tick>0)
				{
					System.out.println(currentThread().getName()+"sale:"+tick--);
				}
			}
		}

		同步的二个前提:
		1.必须要有两个或者两个以上的线程。
		2.必须是多个线程使用同一个锁。

		保证同步中只能有一个线程在运行。
		好处:解决了多线程的安全问题
		弊端:多个线程需要判断锁,较为消耗资源。

		把 synchronized 作为修饰符放在函数上,让函数具有同步性。
		同步函数用的锁是:方法是被对象调用,前面省略this.方法名();
		所以同步函数使用的锁的是:this.

	静态同步函数的锁是所在类的Class对象。类名.class
	静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。

	class Ticket implements Runnable//extends Thread
	{
		private int tick = 100;
		boolean flag = true;
		public void run()
		{		
			if(flag){
				
				while (true)
				{
					synchronized(this)
					//synchronized(Ticket.class)
					{
						if (tick>0)
						{
							System.out.println(currentThread().getName()+"sale:"+tick--);
						}
						
					}
				}
			}
			else
			{
				while(true)
					method();
			}
		}
		public synchronized void method()//this
			//public static synchronized void method()//Ticket.class
			//方法静态,tick也要为静态。
		{
			if (tick>0)
			{
				System.out.println(currentThread().getName()+"method:"+tick--);
			}
				
		}
	}

	class TicketDemo
	{
		public static void main(String[] args)
		{
			Tictet t = new Ticket();
			new Thread(t).start();
			t.flag = false;//变动条件
			new Thread(t).start();
			
		}
	}


回顾单例设计模式:
饿汉式:
class Single
{
	private Single(){}
	private static Single s = new Single();
	public static Single getInstance()
	{
		return s;
	}
}

//双重判断的安全的懒汉式
class Single
{
	private Single(){}
	private static Single s = null;
	public static Single getInstance()
	{
		if(s == null)
		{
			synchronized(Single.class)
			{
				if (s == null)
				{
					s = new Single();
				}
			}
		}
		return s;
	}
}


多线程:死锁问题。
	同步中嵌套同步,但是锁不同。

class Ticket implements Runnable//extends Thread
	{
		private int tick = 100;
		boolean flag = true;
		Object obj  = new Object();
		public void run()
		{		
			if(flag){
				
				while (true)
				{
					synchronized(obj)
					
					{
						method();
					}
				}
			}
			else
			{
				while(true)
					method();
			}
		}
		public synchronized void method()//this
		{
			synchronized(obj)
			{
				if (tick>0)
				{
					System.out.println(currentThread().getName()+"method:"+tick--);
				}
			}
				
		}
	}

	class DeadLockDemo
	{
		public static void main(String[] args)
		{
			Tictet t = new Ticket();
			new Thread(t).start();
			t.flag = false;//变动条件
			new Thread(t).start();
			
		}
	}

//--------------------------------------------------------
//以下是人造一个死锁

class Test implements Runnable
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag = flag;
	}
	public void run()
	{
		
		if (flag)
		{
			//如果不出现死锁,可加上while(true).
			synchronized(MyLock.locka)
			{
				System.out.println("if locka");
				synchronized(MyLock.lockb)
				{
					System.out.println("if lockb");
				}

			}
		}

		else
		{
			synchronized(MyLock.lockb)
			{
				System.out.println("else lockb");
				synchronized(MyLock.locka)
				{
					System.out.println("else locka");
				}

			}

		}

	}
}

class MyLock
{
	static MyLock locka = new MyLock();//老师视频上用Object
	static MyLock lockb = new MyLock();
}
class DeadLockTest
{
	public static void main(String[] args)
	{
		new Thread(new Test(true)).start();
		new Thread(new Test(false)).start();

	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值