您的位置:首页 > 职场人生

黑马程序员-【java基础】-多线程

2015-06-27 09:25 681 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一.多线程概述
java语言的优势之一就是线程处理较为简单。一般操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序被称为一个进程。当一个程序运行时,内部可能包含多个顺序执行流,每个顺序执行流就是一个线程。
进程:同一个操作系统中执行的一个子程序,包含了三部分虚拟CPU,代码,数据。
多进程:同一个操作系统中执行的多个并行的子程序,可以提高CPU的使用率。
线程:同一个进程当中并发执行的子程序流。
多线程:同一个进程中并发执行的多个子程序流。
并发:进程时并发运行的,OS将时间划分为很多时间片段,尽可能均匀分配给正在运行的程序,微观上进程走走停停,宏观上都在运行,这种运行的现象称为并发。
二.线程编程的两种方法
1)Thread类
线程类(Thread)包含了一个可以运行的过程(方法):run()方法。
2)创建一个具体线程的步骤如下:
第一,继承Thread类。
第二,覆盖run方法(就是更新运行过程),实现用户自己的过程。
第三,创建线程实例(就是创建一个线程)
第四,使用线程实例的start()方法启动线程,启动后线程会尽快的去并发执行run()
方法一:继承Thread类
实现步骤:
1.继承Thread类,覆盖run()方法,提供并发运行的过程。
2.创建这个类的实例
3.使用start()方法开启线程。

class MyThread extends Thread
{
	public void run()
	{
		System.out.println("覆盖run()方法");
	}
}
public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Thread t1=new MyThread();
		//调用start()来启动线程,线程启动方法
		t1.start();

	}

}
注:

1.main()方法也是一个线程
2.单核,双核,多核处理器的输出结果会不一样
方法二:实现Runnable接口
实现步骤:
1.实现Runnable接口,实现run()方法,提供并发执行的过程
2.创建这个类的实例,用这个实例作为Thread构造器参数,创建Thread类
3.使用start()方法启动线程

class MyThread2 implements Runnable
{
	
	public void run() {
		System.out.println("覆盖run()方法");
		
	}
}
public class TestThread2{
	public static void main(String[] args) {
		Runnable myThread=new MyThread2();
		Thread t1=new Thread(myThread);
		t1.start();
	}
}


三.线程的5种状态

1) New新建状态
当程序使用new关键字创建了一个线程后,该线程就处于新建状态,此时线程还未启动,当线程对象调用start()方法时,线程启动,进入Runnable状态。
2)Runnable可运行状态
当线程处于Runnable状态时,表示线程准备就绪,等待获取CPU
3)Running运行状态
假如线程获取了CPU,则进入Running状态,开始执行线程体,开始执行run方法。
4)Block阻塞状态
当如下情况下,线程会进入阻塞状态:
1.线程调用了sleep()方法主动放弃所占CPU资源。
2.线程调用了一个阻塞式IO方法,在该方法返回前,该线程被阻塞。
当正在执行的线程被阻塞时,其他线程就获得执行权限,
5)Dead死亡状态
1.当线程的run方法执行结束,线程进入Dead状态
2.需要注意的是,不要试图对一个已经死亡的线程进行start()方法,线程死亡后将不能再次作为线程执行,系统会抛出IllegalThreadStateException异常



四.线程的同步
多线程并发访问同一个对象,如果不对线程进行同步控制,破坏了原子操作,则会造成临界资源的数据不一致。
每一个对象都有一个互斥的锁标记和一个锁池,当线程拥有这个对象的锁标记时才能访问这个资源,没有锁标记便进入锁池,保证在同步代码块中只有一个线程,解决了多线程的同步控制问题。
synchronized修饰代码块:对括号内的对象object加锁,只有拿到对象锁标记的线程才能进入该代码块。
class Test implements Runnable
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag=flag;
	}
	public void run()
	{
		while(true)
		{
			if(flag==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  locka");
					synchronized(myLock.locka)
					{
						System.out.println("else  lockb");
					}
				}
			}
		}
	}
}
class myLock
{
	static Object locka=new Object();
	static Object lockb=new Object();
}
class  DeadLockTest
{
	public static void main(String[] args) 
	{
		Thread d1=new Thread(new Test(true));
		Thread d2=new Thread(new Test(false));
		d1.start();
		d2.start();

	}
}


注意:
1.静态方法可以是同步方法,但是他所锁的并不是当前对象,是类对象
2.抽象方法不能是synchronized同步的方法
3.构造方法不能是synchronized同步的方法

1.等待唤醒机制:

Wait, notify() notifyAll() 都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。



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

因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。

不可以对不同锁中的线程进行唤醒。

即等待和唤醒必须是同一个锁。

2.如何停止线程?

开启多线程运行,运行代码通常是循环结构的,只要控制住循环,就可以让run方法结束,从而线程结束。

3.join:当A线程执行到了B线程的.join方法时,A就会等待,等B线程都执行完了,A才执行。Join可以用来临时加入线程执行。

3.并行和并发

并行:是在逻辑上同时发生,指在某一个时间内同时运行多个程序。

并发:物理上同时发生,指在某一个时间点上同时运行多个程序。

4.JVM虚拟机的启动是单线程还是多线程?

多线程,因为垃圾回收也要先启动,否则很容易出现内存溢出。

最简单的也是垃圾回收线程和主线程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: