黑马程序员——多线程篇

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

进程与线程

    学习多线程,首先要知道什么是进程,什么是线程

    ①.进程:进程是一个执行的程序,指的是从代码加载、执行到执行结束的一个完整的过程。

    ②.多进程:计算机同时运行两个或者更多的程序。

    ③.线程:线程是比进程小的执行单位,一个进程可以通过运行多个线程来并发执行多项任务。

    ④.多线程在单个程序中同时运行多个线程来完成不同的工作。

多线程概述

    ①.多线程是实现并发的一种有效手段,一个进程可以通过运行多个线程来并发地执行多项任务,而多个线程之间的调度执行,有系统来决定。

    ②.多个线程可以共享代码段、数据段和诸如打开的文件等的系统资源。

多线程的好处

    ①.线程共享相同的地址空间,提高CPU使用率。

    ②.线程共同分享同一个进程,提高应用程序的使用率。

    ③.由于同一个进程内的线程共享内存和文件,所以线程之间相互通信不必调用内核。

多线程的实现方式

    Java的多线程机制提供了两种方式实现多线程变成,一种是通过继承Thread类来实现,一种是通过实现Runnable接口实现。

1.继承Thread类

    ①.重载该类的run()方法,把需要使用多线程运行的代码放入该方法。

    ②.创建线程对象并用该对象调用start()方法。

public class MyThread extends Thread {
	@Override
	public void run() {
		for (int x = 0; x < 200; x++) {
			System.out.println(x);
		}
	}
}

2.实现runnable接口

    ①.实现run()方法,把需要使用多线程运行的代码放入该方法。

    ②.runnable中只有一个run()方法,没有提供任何东西来支持多线程,所以它必须通过Thread类的框架实现多线程。

    ③.通过Thread类的构造函数,public Thread(Runnable target)来实现。

public class MyRunnable implements Runnable {
	@Override
	public void run() {
		for (int x = 0; x < 100; x++) {
			// 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用
			System.out.println(Thread.currentThread().getName() + ":" + x);
		}
	}

}

3.为什么定义这两种方式实现多线程

    Java不支持多继承,所以如果用户的类已经继承了一个类,而有需要多线程机制的支持,此时继承Thread类就不现实了。所以Runnable接口在这种情况下就很实用。

4.run()与start()的区别

    ①.run(),仅仅封装了代码,直接调用为普通方法。

    ②.start(),会初始化一些和线程有关的资源,而后会调用run()方法。

线程的调度和优先级

1.线程的调度

    ①.分时调度

    ②.抢占式调度(Java采用的就是该调度模式)

2.线程的优先级

    ①.默认优先级是5

    ②.优先级的范围是0—10。可通过getPriority()方法来获取线程的优先级,通过setPriority()来设置线程的优先级。

线程的常用方法

    ①.void start()     使该线程开始执行;Java 虚拟机调用该线程的 run 方法

    ②.String getName()     返回该线程的名称。 

    ③.void setName(String name)       改变线程名称,使之与参数 name 相同。 

线程的控制

    ①.void interrupt()   中断线程。

    ②.void join()    等待该线程终止。

    ③.void setDaemon(boolean on)    将该线程标记为守护线程或用户线程。 

    ④.static void sleep(long millis)    在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。 

    ⑤.static void yield()    暂停当前正在执行的线程对象,并执行其他线程。 

线程的生命周期

    

多线程的安全问题

1.判断依据

    ①.是否有多线程环境

    ②.是否有共享数据

    ③.是否有多条语句操作共享数据

2.解决的思想

    把多条语句操作共享数据的代码给包成一个整体,让某个线程在执行的时候,别人不能执行。

线程的同步

1.同步的定义

    ①.所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回,同时其他线程也不同调用这个方法。

    ②.同步解决的是共享资源冲突的问题。

2.同步的用法

    ①.Java语言提供两个基本的同步用法:同步方法和同步语句(同步代码块)。

    

线程的死锁问题

    死锁问题出现在同步嵌套中,线程不结束就不会释放锁,出现相互等待的情况。

public class DieLock extends Thread {
	private boolean flag;
	public DieLock(boolean flag) {
		this.flag = flag;
	}
	@Override
	public void run() {
		if (flag) {
			synchronized (MyLock.objA) {
				System.out.println("if objA");
				synchronized (MyLock.objB) {
					System.out.println("if objB");
				}
			}
		} else {
			synchronized (MyLock.objB) {
				System.out.println("else objB");
				synchronized (MyLock.objA) {
					System.out.println("else objA");
				}
			}
		}
	}
}

线程间通信问题

1.定义

    线程间通信是指不同种类的线程间,对同一种资源操作。

2.方式

    ①.基本方式

    ②.同步机制:不同种类线程都加锁,必须是同一把锁。

    ③.等待唤醒机制(依次执行):加入flag标记,加入wait()方法,加入notify()方法。

    注意:wait()自动释放锁,醒来时原地起步。并且wait()之后不抢执行权。

public class Student {
	private String name;
	private int age;
	private boolean flag; // 默认情况是没有数据,如果是true,说明有数据

	public synchronized void set(String name, int age) {
		// 如果有数据,就等待
		if (this.flag) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		// 设置数据
		this.name = name;
		this.age = age;

		// 修改标记
		this.flag = true;
		this.notify();
	}

	public synchronized void get() {
		// 如果没有数据,就等待
		if (!this.flag) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		// 获取数据
		System.out.println(this.name + "---" + this.age);

		// 修改标记
		this.flag = false;
		this.notify();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值