黑马程序员——多线程(一)

------- " target="blank">android培训" target="blank">java培训、期待与您交流! ----------


-多线程的概述

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

2、线程的概念:进程中的一个独立的控制单元,控制着进程的执行。(一个进程中至少有一个线程)

3、多线程存在的意义

4、多线程的创建方式

 5、多线程的特征

6、Java VM 启动的时候会有一个进程java.exe

  该进程中至少一个线程辅助java程序的执行,而且这个线程运行的代码存在于main方法中
  该线程称之为主线程。

-多线程的创建方式一

1、定义类继承Thread

2、复写Thread类中的run方法 (作用:将自定义代码存储在run方法中,让线程运行)

3、创建继承了Thread类的对象,调用线程的start方法(作用:就是启动线程,调用run方法)

package day11_Thread;

/**
 * 学习多线程(1、进程   2、线程   3、多线程存在的意义   4、多线程的创建方式   5、多线程的特征)
 * 进程:是一个正在执行的程序。
 * 		每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。
 * 线程:就是进程中一个独立的控制单元,它控制着进程的执行。
 * (一个进程中至少有一个线程)
 * 
 * Java VM 启动的时候会有一个进程java.exe
 * 		该进程中至少一个线程辅助java程序的执行,而且这个线程运行的代码存在于main方法中
 * 		该线程称之为主线程。
 * 
 * 扩展:其实进一步可以说jvm 启动不止一个线程,还有辅助垃圾回收机制的线程。
 * 
 * 
 * 一:如何在自定义的代码中,自定义一个线程呢?
 * 		通过对查找api文档,ajva已经提供了对线程这类事物的描述,就是Thread类。	
 * 		
 * 创建线程的第一种方式:继承Thread类。
 * 步骤:1、定义类继承Thread
 * 		2、复写Thread类中的run方法 (作用:将自定义代码存储在run方法中,让线程运行)
 * 		3、创建继承了Thread类的对象,调用线程的start方法(作用:就是启动线程,调用run方法)
 * 
 * 发现运行结果每一次都不同,这是因为多个线程都获取到了cpu执行权,cpu执行到谁,
 * 		谁就运行——这就是多线程的一个特征:随机性
 * 
 * @author Administrator
 *
 */

class ThreadDemo extends Thread {
	public void run() {
		for(int i=0;i<1000;i++){
			System.out.println("Thread run..."+i);
		}
	}
}
public class Day11_01_ThreadDemo {

	public static void main(String[] args) {
		//for(int i=0;i<100;i++)
		//	System.out.println("hello world ! "+i);
		
		ThreadDemo t = new ThreadDemo();//创建一个线程
		t.start();//开启程序并执行该线程的run方法
		//t.run();//仅仅是对象方法的调用,线程虽然创建了,但并没有执行(面试考点)
		
		for(int i=0;i<1000;i++){
			System.out.println("mainThread run......"+i);
		}
	}

}


 -获取线程对象及其名称

每个线程都有自己默认的编号名称:Thread-编号,该编号从0开始。

static Thread currentThread():获取当前线程对象

getName():获取线程的名称

设置线程名称:通过setName()方法或者构造函数


-多线程练习1:创建两个线程,与主线程main交替执行

package day11_Thread;

/**
 * 多线程练习1:创建两个线程,与主线程main交替执行
 * @author Administrator
 */

class ThreadPractice1 extends Thread {
	
	//private String name;
	public ThreadPractice1(String name) {
		//this.name = name;
		super(name);
	}
	
	public void run() {
		for(int i=0;i<100;i++){
			//System.out.println(name+" Thread run..."+i);
			//System.out.println(this.getName()+" Thread run..."+i);
			System.out.println((Thread.currentThread()==this)+"...."+this.getName()+" Thread run..."+i);
		}
	}
}

public class Day11_04_ThreadPractice1 {

	public static void main(String[] args) {
		
		ThreadPractice1 t1 = new ThreadPractice1("firstName");
		ThreadPractice1 t2 = new ThreadPractice1("secondName");
		t1.start();
		t2.start();
		
		for(int i=0;i<100;i++){
			System.out.println("mainThread run..."+i);
		}
	}

}



-线程的状态

创建——start()——>运行——sleep(time)——>冻结

冻结——notify()/notifyAll()——>运行

运行——stop()——>消亡


 -创建线程的第二种方式(多线程练习2:简单的售票程序(实现多窗口同时售票))

1、自定义类实现Runnable接口  

2、覆盖Runnable接口中的run()方法  

3、通过Thread类建立线程对象  

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

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

package day11_Thread;
/**
 * 多线程练习2:简单的售票程序(实现多窗口同时售票)
 * 
 * 创建线程的第二种方式:实现Runable接口
 * 步骤:
 * 		1、自定义类实现Runnable接口
 * 		2、覆盖Runnable接口中的run()方法
 * 		(将线程要运行的代码存放在该run方法中)
 * 		3、通过Thread类建立线程对象
 * 		4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数
 * 		(将Runnable接口的子类对象传递给Thread的构造函数目的是因为自定义的run()
 * 		  方法所属的对象是Runnable接口的子类对象,所以要让线程去指定对象的run()方法,
 * 		  必须明确该run()方法所属对象)
 * 		5、调用Thread类的start()方法开启线程并调用Runnable接口子类的run()方法
 * 
 * 创建线程的两种方式有什么区别?(***面试考点***)
 * 		继承Thread类:线程代码存放在Thread子类run()方法中
 * 		实现Runnable接口:线程代码存放在接口子类的run()方法中
 * 		实现Runnable接口好处:避免了单继承的局限性(所以建议使用实现方式创建线程)
 * @author Administrator
 *
 */

class SellTicket1 implements Runnable // extends Thread 
{
	private int tickets = 100;
	//private static int tickets = 100;
	public void run(){
		while(true){
			if(tickets>0){
				try {
					Thread.sleep(20);//将会出现线程安全问题
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+" -// sellTicket: "+tickets--);
			}
		}
	}
}
public class Day11_08_RunnableDemo {

	public static void main(String[] args) {
		
		SellTicket1 s = new SellTicket1();
		
		Thread t1 = new Thread(s);
		Thread t2 = new Thread(s);
		Thread t3 = new Thread(s);
		Thread t4 = new Thread(s);
		
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		
	}

}



-
创建线程的两种方式有的区别

通过Runnable接口创建线程:

1、可以将cpu,代码和数据分开,形成清晰的模型

2、线程体run()方法所在的类可以从其他类继承一些有用的属性和方法

3、有利 于保持程序设计风格的一致。

直接继承Thread类创建对象:

1Thread子类无法再从其他类继承(受限于java 语言的单继承模式)

2、编写简单,run()方法的当前对象就是线程对象,可直接操作。实际应用中几乎都是采取第一种方式,因为没有继承的局限性。

实现Runnable接口好处:避免了单继承的局限性(所以建议使用实现方式创建线程)


你可能感兴趣的:(黑马程序员——多线程(一))