天天看点

黑马程序员:Java多线程

----------   android培训、java培训、期待与您交流! ----------

进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。

该顺序是一个执行路径,或者叫一个控制单元。

线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。一个进程中至少有一个线程。

创建线程的2种方式:

1.继承Thread类

实现步骤:

1,定义类继承Thread。

2,复写Thread类中的run方法。

 目的:将自定义代码存储在run方法。让线程运行。

3,调用线程的start方法,

 该方法两个作用:启动线程,调用run方法。

2.实现Runnable接口

步骤:

1,定义类实现Runnable接口

2,覆盖Runnable接口中的run方法。

 将线程要运行的代码存放在该run方法中。

3,通过Thread类建立线程对象。

4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。

 为什么要将Runnable接口的子类对象传递给Thread的构造函数。

 因为,自定义的run方法所属的对象是Runnable接口的子类对象。

 所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。

5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

3.实现Runnable方式和继承Thread方式有什么区别呢?

实现Runnable方式好处:避免了单继承的局限性。

所以创建线程建议使用实现Runnable方式

两种方式区别:

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

实现Runnable,线程代码存在接口的子类的run方法。

线程的7种状态:

有的书上也只有认为前五种状态:而将“锁池”和“等待池”都看成是“阻塞”状态的特殊情况:这种认识也是正确的,但是将“锁池”和“等待池”单独分离出来有利于对程序的理解

1,初始状态,线程创建,线程对象调用start()方法。

2,可运行状态,也就是等待Cpu资源,等待运行的状态。

3,运行状态,获得了cpu资源,正在运行状态。

4,阻塞状态,也就是让出cpu资源,进入一种等待状态,而且不是可运行状态,有三种情况会进入阻塞状态。

1)如等待输入(输入设备进行处理,而CPU不处理),则放入阻塞,直到输入完毕,阻塞结束后会进入可运行状态。

2)线程休眠,线程对象调用sleep()方法,阻塞结束后会进入可运行状态。

3)线程对象2调用线程对象1的join()方法,那么线程对象2进入阻塞状态,直到线程对象1中止。

5,中止状态,也就是执行结束。

6,锁池状态

7,等待队列

(7状态的图)

黑马程序员:Java多线程

(5状态的图)

黑马程序员:Java多线程

线程中存在的一些锁:

java线程中默认的锁是this锁

1.同步代码块synchronized(obj)中的锁是obj锁(obj可以使任意对象)

2.同步函数中的锁是this锁

3.静态同步函数中的锁是Class对象(类名.class)

线程中的一些方法及与其相关的方法:

1.wait()、notify()、notifyAll()

wait()等待的线程都存在于内存线程池中。

notify()唤醒线程池中的线程,一般是唤醒最先等待的线程。

notifyAll()唤醒全部

以上三个全部用在同步中,使用必须要有该对象的监视器(锁),默认是this

 2.停止线程

stop()方法已经过时

当线程处于冻结状态时,要把他停止的话,就必须把他唤醒,判断执行条件,最终结束线程。

Thread类提供了该方法interrupt,就是强制让线程恢复到运行状态中来

3.守护线程

setDaemon(boolean on)

当on为true时,该线程则为守护线程

当正在运行的线程都是守护线程时,Java 虚拟机退出。

4.join方法

当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行

join可以用来临时加入线程执行

5.优先级

优先级总共有10级(1-10)

setPriority(int newPriority)设置线程的优先级

getPriority()得到线程优先级

优先级的一些常量:

MAX_PRIORITY:最高优先级-->10级

MIN_PRIORITY:最低优先级-->1级

NORM_PRIORITY:默认优先级-->5级(大多数未定义优先级的线程的优先级都为5级)

优先级越大,则获取cpu资源的概率越大

6.yield方法

暂停当前正在执行的线程对象,并执行其他线程

线程中的死锁问题:

线程中最大的问题就是会在同步的过程中产生死锁,而产生死锁了就会无限的无效的消耗系统资源,所以在线程中应该尽量避免死锁

java中解决死锁是用synchronized关键字进行修饰,也就是用同步去解决死锁

实现同步是用synchronized方法和synchronized代码块

 死锁产生的原因:

public class DeadLockDemo {
	public static void main(String[] args) {
		Thread t1 = new Thread(new Test(true));
		Thread t2 = new Thread(new Test(false));
		t1.start();
		t2.start();
	}

}

class MyLock
{
	static Object locka = new Object();
	static Object lockb = new Object();
}

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(Thread.currentThread().getName()+"...if locka ");
					synchronized(MyLock.lockb)
					{
						System.out.println(Thread.currentThread().getName()+"..if lockb");					
					}
				}
			}
		}
		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");
					}
				}
			}
		}
	}
}
           

在上面那代码中存在着两个锁locka和lockb,和两个线程t1,t2,当t1拿到locka锁,申请lockb锁,但是此时t2已经拿到lockb锁,而它也在申请locka锁,这时候他们分别都拿着对方锁要的锁不放,这样就就会一直僵持下去,就这样一直消耗着系统资源。

所以我们以后写代码的时候一定要避免死锁。

----------   android培训、java培训、期待与您交流! ----------

详情请查看:http://edu.csdn.net/heima/