黑马程序员 java多线程

                                                                                          黑马程序员  java多线程

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

1.进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径或者叫一个控制单元。


2.线程:就是进程中的一个独立的控制单元,线程在控制着进程的执行。


3.一个进程中至少有一个线程。


4.java VM 启动的时候会有一个进程java.exe,该进程中至少有一个线程负责java程序的执行,而且这个线程进行的代码存在于main方法中,该线程称之为主线程。(扩展:其实jvm启动不止一个线程,还有负责垃圾回收机制的线线程)


5.创建线程的方式一:

(1)继承Thread类,创建子类对象的同时就创建了线程,创建多少个子类对象就有多少条线程。

步骤:a.定义类继承Thread。

      b.复写Thread类中的run方法。目的:将自定义代码存储在 

        run方法。让线程运行。

      c.调用线程的start方法。该方法两个作用:启动线程;

        调用 run方法。

d.要是只调用run方法,这仅仅是调用对象的方法,而没有启动线程。

(2)多线程的运行其实是在互相抢cpu的执行权。所以多线程有一个特性:随机性。

(3)Thread类中的run方法用于存储线程要运行的代码。

(4)线程运行状态:运行、临时状态、冻结:sleep(time)时间到了就会醒;wait(等待)需要被notify(唤醒)才会醒、消亡(stop();run方法结束)。

(5)获取线程名称:因为定义类继承Thread,所以直接用this.getName调用,线程都有自己默认的名称:Thread-编号,编号从0开始。

(6)改变线程名称:子类构造函数中可以调用父类的super(name);

(7)Thraed.currentThraed().getName:获取当前线程对象的名称(通用)


6.创建线程的方式二:实现Runnable接口

步骤:

a.定义类实现Runnable接口

b.覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。

c.通过Thread类建立线程对象

d.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。因为自定义的run方法所属的对象是Runnable接口的子类对象,所以要让线程去指定对象的run方法。Ticket t=new Ticket();

Thread t1=new Thread(t)

(1)实现方式和继承方式的区别:

继承Thread:线程代码存放Thread子类run方法中。

实现Runnable,线程代码存放接口的子类的run方法。实现方式的好处是避免了单继承的局限性。


7.多线程的运行出现安全问题。

(1)问题的原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。

(2)解决办法:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。

(3)如何找问题:

明确哪些代码是多线程运行代码;明确共享数据;明确多线程运行代码中哪些语句是操作共享数据的。

(4)多线程的安全问题解决方式:同步代码块。

synchronied(对象)

{需要被同步的代码}

(5)同步的前提:

A.必须要有两个或者两个以上的线程。

B.必须是多个线程使用同一个锁。

C.必须保证同步中只能有一个线程在运行

(6)弊端:多个线程需要判断锁,较为消耗资源。


8.同步函数的锁是synchronized(this);静态同步函数的锁是

synchronized(类名.class)


9.多线程-单例设计模式

懒汉式的特点是延迟加载实例,在多线程访问时,会出现安全问题,可以使用同步代码块或同步函数来解决,但比较低效,可以通过双重判断的形式来解决低效问题。同步所使用的锁是该类字节码文件对象。具体示例如下:

//多线程单例设计模式—懒汉式
class Single
{
  private static Single s=null;
  private Single(){};
  public static Single getInstance()
  {
				if(s==null)
  		{
  			synchronized(Single.class)
  			{
  				if(s==null)
  					s=new Single();
  			}
  		}
				return s;
  }
}



10.死锁

//死锁示例
class DeadLockTest 
{
	public static void main(String[] args) 
	{
		Thread t1=new Thread(new Test(true));//创建线程并操作Test类中的run方法
		Thread t2=new Thread(new Test(false));
		t1.start();//启动线程
		t2.start();
	}
}
class Test implements Runnable
{
	private boolean flag;
	//建立构造函数初始化Test对象
	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
		{
			while(true)
			{
				synchronized(MyLock.lockb)
				{
					System.out.println("else lockb");
				
					synchronized(MyLock.locka)
					{
						System.out.println("else locka");
					}
				}
			}
			
		}
	}
}
class MyLock
{
	//创建两个不同的锁
	static Object locka=new Object();
	static Object lockb=new Object();
}



11.线程间通信:其实就是多个线程在操作同一个资源,但是操作的动作不同。


12.public final void wait() throw InterruptedException

Wait方法抛出了异常,用的时候要try和catch。


13.wait(),notify(),notifyAll()只能在同步里面用。因为要对持有锁的线程操作,而只有同步才具有锁,所以要使用在同步中。


14.为什么这些操作线程的方法要定义Object类中呢?

因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。不可以对不同锁中的线程进行唤醒。也就是说等待和唤醒必须是同一个锁,所以要:对象.wait,对象.notify。


15.而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。


16.DK1.5中提供了多线程升级解决方案,将同步Synchronized替换成显示的Lock操作。将Object中的wait,notify,notifyAll,替换了Condition对象。

//生产者与消费者JDK5.0升级版示例
import java.util.concurrent.locks.*;
class ProducerConsumerDemo 
{
	public static void main(String[] args) 
	{
		//将类实例化
		Resource r=new Resource();
		Producer pro=new Producer(r);
		Consumer con=new Consumer(r);
		//创建线程并操作对应类中的run方法
		Thread t1=new Thread(pro);
		Thread t2=new Thread(pro);
		Thread t3=new Thread(con);
		Thread t4=new Thread(con);
		//启动线程
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
class Resource
{
	private String name;
	private int count=1;
	private boolean flag=false;
	private Lock lock=new ReentrantLock();//创建锁
	//lock.newCondition()返回一个Condition对象
	private Condition condition_pro=lock.newCondition();
	private Condition condition_con=lock.newCondition();
	public void set(String name)throws InterruptedException
	{
		lock.lock();//调用锁
		try
		{
			while(flag)
				condition_pro.await();//等待
			this.name=name+"-----"+count++;
			System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
			flag=true;
			condition_con.signal();//唤醒对方
		}
		finally
		{
			lock.unlock();//解锁
		}
	}
	public void out()throws InterruptedException
	{
		lock.lock();
		try
		{
			while(!flag)
				condition_con.await();
			System.out.println(Thread.currentThread().getName()+"...消费者......."+this.name);
			flag=false;
			condition_pro.signal();
		}
		finally
		{
			lock.unlock();
		}
	}
}
class Producer implements Runnable
{
	private Resource res;
	Producer(Resource res)
	{
		this.res=res;
	}
	public void run()
	{
		while(true)
		{
			try
			{
				res.set("+商品");
			}
			catch (InterruptedException e)
			{
			}
			
		}
	}
}
class Consumer implements Runnable
{
	private Resource res;
	Consumer(Resource res)
	{
		this.res=res;
	}
	public void run()
	{
		while(true)
		{
			try
			{
				res.out();
			}
			catch (InterruptedException e)
			{
			}
			
		}
	}
}



17.停止线程

定义循环结束标记:因为线程运行代码一般都是循环,只要控制了循环即可。

使用interrupt(中断)方法:该方法是结束线程的交结状态,使线程回到运行状态中来。

注:stop方法已经过时不再使用。


18.守护线程:setDaemon(boolean on),该方法必须在启动线程前调用。守护线程依赖于主线程,当主线程运行结束,守护线程也跟着结束。例子:

Thread t=new Thread(d);

t.setDaemon(true);

t.start();


19.join方法

Thread t1=new Thread(d);

Thread t2=new Thread(d);

t1.start();

t1.join();

t2.start();

1线程夺取执行权,2线程和主线程冻结,先运行完1线程,然后2线程和主线程争夺执行权,交替运行。

Thread t1=new Thread(d);

Thread t2=new Thread(d);

t1.start();

t2.start();

t1.join();

1线程和2线程争夺执行权,交替运行,主线程冻结,直到1线程运行完毕,2线程如果没运行完,它会跟主线程争夺执行权,交替运行。

20.优先级

t1.setPriority(Thread.MAX_PRIORITY);最高优先级

t2.setPriority(Thread.MIN_PRIORITY);最低优先级

t3.setPriority(Thread.NORM_PRIORITY);默认优先级

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值