Java常用工具类--多线程

进程的概念:

Java常用工具类--多线程_第1张图片

线程的概念:

 

Java常用工具类--多线程_第2张图片

Java常用工具类--多线程_第3张图片


Thread类和Runnable接口介绍:

进程的创建:

Java常用工具类--多线程_第4张图片

Thread介绍:

Java常用工具类--多线程_第5张图片

Thread的常用方法:

Java常用工具类--多线程_第6张图片

Runnable接口:

Java常用工具类--多线程_第7张图片


线程创建:
通过Thread类创建线程:

Java常用工具类--多线程_第8张图片

测试代码1:

package com.imooc.thread;

//创建一个新的线程
class MyThread extends Thread {
	public void run() {
		System.out.println(getName() + "该线程正在执行!");
	}
}

public class ThreadTest {

	public static void main(String[] args) {

		System.out.println("主线程1");
		MyThread mt = new MyThread();
		// 启动线程
		// 线程只能执行一次
		mt.start();

		System.out.println("主线程2");

	}

}

输出结果:

主线程1
主线程2
Thread-0该线程正在执行!

测试代码2:

package com.imooc.thread1;
//创建线程类
class MyThread extends Thread{
	public MyThread(String name) {
		super(name);
	}
	public void run() {
		for (int i =1;i<=10;i++) {
			System.out.println(getName()+"正在运行"+"第"+i+"次");
		}
	}
}

public class ThreadTest {

	public static void main(String[] args) {
		MyThread mt1 = new MyThread("线程1");
		MyThread mt2 = new MyThread("线程2");
		mt1.start();
		mt2.start();

	}

}

输出结果是随机的,由于对于时间片的分配是随机的

输出结果1:

线程1正在运行第1次
线程2正在运行第1次
线程1正在运行第2次
线程2正在运行第2次
线程1正在运行第3次
线程2正在运行第3次
线程1正在运行第4次
线程2正在运行第4次
线程1正在运行第5次
线程1正在运行第6次
线程1正在运行第7次
线程1正在运行第8次
线程1正在运行第9次
线程1正在运行第10次
线程2正在运行第5次
线程2正在运行第6次
线程2正在运行第7次
线程2正在运行第8次
线程2正在运行第9次
线程2正在运行第10次

输出结果2:

线程1正在运行第1次
线程2正在运行第1次
线程1正在运行第2次
线程2正在运行第2次
线程1正在运行第3次
线程2正在运行第3次
线程1正在运行第4次
线程2正在运行第4次
线程1正在运行第5次
线程2正在运行第5次
线程1正在运行第6次
线程1正在运行第7次
线程1正在运行第8次
线程2正在运行第6次
线程1正在运行第9次
线程2正在运行第7次
线程2正在运行第8次
线程1正在运行第10次
线程2正在运行第9次
线程2正在运行第10次

通过实现Runnable接口创建线程:

Java常用工具类--多线程_第9张图片

测试代码:

package com.imooc.runnable;

class PrintRunnable implements Runnable {
	// 类内代码可以共享
	int i = 1;

	@Override
	public void run() {
		while (i <= 10)
			System.out.println(Thread.currentThread().getName() + "正在运行" + (i++));

	}
}

public class Test {
	public static void main(String[] args) {
		PrintRunnable pr = new PrintRunnable();
		Thread t1 = new Thread(pr);
		t1.start();

//		PrintRunnable pr1 = new PrintRunnable();
		Thread t2 = new Thread(pr);
		t2.start();
	}

}

输出结果是随机的

输出结果1:

Thread-0正在运行1
Thread-1正在运行2
Thread-1正在运行4
Thread-0正在运行3
Thread-1正在运行5
Thread-0正在运行6
Thread-0正在运行8
Thread-0正在运行9
Thread-1正在运行7
Thread-0正在运行10

输出结果:

Thread-0正在运行1
Thread-1正在运行1
Thread-0正在运行2
Thread-1正在运行3
Thread-0正在运行4
Thread-1正在运行5
Thread-0正在运行6
Thread-1正在运行7
Thread-0正在运行8
Thread-1正在运行9
Thread-0正在运行10

Runnable接口的实现顺序:


编程练习:
 

1、通过实现Runnable接口的方式创建线程类Cat和Dog,run()方法实现的功能为:加入一个循环长度为3的for循环,分别循环输出信息“A cat”和“A dog”。

2、在测试类中分别创建Cat和Dog类的对象,启动两个线程。

3、在测试类中创建一个循环长度为3的for循环,打印输出信息“main thread”。

测试代码:

Cat类:

package test017;

class Cat implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 3; i++) {
			System.out.println(Thread.currentThread().getName() + "A cat");
		}

	}

}

Dog类:

package test017;

class Dog implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 3; i++) {
			System.out.println(Thread.currentThread().getName() + "A dog");
		}

	}

}

测试类:
 

package test017;

public class ThreadTest {
	public static void main(String[] args) {
		for (int i = 0; i < 3; i++) {
			System.out.println("main thread");
		}

		Cat one = new Cat();
		Dog two = new Dog();
		Thread t1 = new Thread(one);
		Thread t2 = new Thread(two);

		t1.start();
		t2.start();

	}

}

输出结果:
 

main thread
main thread
main thread
Thread-0A cat
Thread-0A cat
Thread-0A cat
Thread-1A dog
Thread-1A dog
Thread-1A dog

线程的状态和生命周期:

线程的状态:
 

Java常用工具类--多线程_第10张图片

线程的生命周期:

Java常用工具类--多线程_第11张图片


sleep方法的使用:
 

Java常用工具类--多线程_第12张图片

测试代码:sleep( )方法在调用时需要捕获一个中断异常

package com.imooc.sleep;

class MyThread implements Runnable {

	public void run() {
		for (int i = 1; i <= 15; i++) {
			System.out.println(Thread.currentThread().getName() + "正在运行" + "第" + i + "次");
			try {
				// 休眠1000ms以后,重新变成可运行状态,等待获取cpu的使用权
				//sleep( )方法在调用时需要捕获一个中断异常
				Thread.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

public class SleepDemo {

	public static void main(String[] args) {
		MyThread mt = new MyThread();

		Thread t = new Thread(mt);
		t.start();

		Thread t1 = new Thread(mt);
		t1.start();

	}

}

输出结果:
在线程1休眠的时候,线程2更可能获得cpu的使用权,然后就是线程2休眠,线程1更可能获得cpu的使用权,因此会出现依次交替饿结果

Thread-0正在运行第1次
Thread-1正在运行第1次
Thread-1正在运行第2次
Thread-0正在运行第2次
Thread-1正在运行第3次
Thread-0正在运行第3次
Thread-1正在运行第4次
Thread-0正在运行第4次
Thread-1正在运行第5次
Thread-0正在运行第5次
Thread-1正在运行第6次
Thread-0正在运行第6次
Thread-1正在运行第7次
Thread-0正在运行第7次
Thread-1正在运行第8次
Thread-0正在运行第8次
Thread-1正在运行第9次
Thread-0正在运行第9次
Thread-1正在运行第10次
Thread-0正在运行第10次
Thread-0正在运行第11次
Thread-1正在运行第11次
Thread-1正在运行第12次
Thread-0正在运行第12次
Thread-1正在运行第13次
Thread-0正在运行第13次
Thread-1正在运行第14次
Thread-0正在运行第14次
Thread-0正在运行第15次
Thread-1正在运行第15次

编程练习:
 

Java常用工具类--多线程_第13张图片

Letter类:

package test018;

class Letter implements Runnable {
	char[] letter = new char[26];

	public Letter() {
		for (int i = 0; i <= 25; i++) {
			letter[i] = (char) (i + 97);
		}
	}

	public void run() {
		Letter chars = new Letter();
		for (int i = 0; i <= 25; i++) {
			System.out.print(chars.letter[i] + " ");
			try {
				// 休眠1000ms以后,重新变成可运行状态,等待获取cpu的使用权
				// sleep( )方法在调用时需要捕获一个中断异常
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

LetterTest类:

package test018;

public class Test {
	public static void main(String[] args) {
		Letter one = new Letter();
		Thread t = new Thread(one);
		t.start();
	}

}

输出结果:

a b c d e f g h i j k l m n o p q r s t u v w x y z 

join方法的使用:

Java常用工具类--多线程_第14张图片

测试:

在不使用join方法的时候:
 

package com.imooc.join;

class MyThread extends Thread {
	public void run() {
		for (int i = 1; i < 21; i++) {
			System.out.println(getName() + "正在执行" + i + "次");
		}

	}

}

public class JoinDemo {

	public static void main(String[] args) {
		MyThread mt = new MyThread();
		mt.start();
//		try {
//			mt.join();
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}

		for (int i = 1; i < 21; i++) {
			System.out.println("主进程" + "正在执行" + i + "次");
		}
	}

}

输出结果:随机输出,

Thread-0正在执行1次
Thread-0正在执行2次
主进程正在执行1次
Thread-0正在执行3次
Thread-0正在执行4次
Thread-0正在执行5次
Thread-0正在执行6次
Thread-0正在执行7次
Thread-0正在执行8次
Thread-0正在执行9次
Thread-0正在执行10次
Thread-0正在执行11次
Thread-0正在执行12次
Thread-0正在执行13次
Thread-0正在执行14次
Thread-0正在执行15次
Thread-0正在执行16次
Thread-0正在执行17次
Thread-0正在执行18次
Thread-0正在执行19次
Thread-0正在执行20次
主进程正在执行2次
主进程正在执行3次
主进程正在执行4次
主进程正在执行5次
主进程正在执行6次
主进程正在执行7次
主进程正在执行8次
主进程正在执行9次
主进程正在执行10次
主进程正在执行11次
主进程正在执行12次
主进程正在执行13次
主进程正在执行14次
主进程正在执行15次
主进程正在执行16次
主进程正在执行17次
主进程正在执行18次
主进程正在执行19次
主进程正在执行20次

加入join后代码:有可能会出现异常,所以就要捕获异常

package com.imooc.join;

class MyThread extends Thread {
	public void run() {
		for (int i = 1; i < 21; i++) {
			System.out.println(getName() + "正在执行" + i + "次");
		}

	}

}

public class JoinDemo {

	public static void main(String[] args) {
		MyThread mt = new MyThread();
		mt.start();
		try {
			mt.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		for (int i = 1; i < 21; i++) {
			System.out.println("主进程" + "正在执行" + i + "次");
		}
	}

}

输出结果:调用join后,会先执行Thread-0
 

Thread-0正在执行1次
Thread-0正在执行2次
Thread-0正在执行3次
Thread-0正在执行4次
Thread-0正在执行5次
Thread-0正在执行6次
Thread-0正在执行7次
Thread-0正在执行8次
Thread-0正在执行9次
Thread-0正在执行10次
Thread-0正在执行11次
Thread-0正在执行12次
Thread-0正在执行13次
Thread-0正在执行14次
Thread-0正在执行15次
Thread-0正在执行16次
Thread-0正在执行17次
Thread-0正在执行18次
Thread-0正在执行19次
Thread-0正在执行20次
主进程正在执行1次
主进程正在执行2次
主进程正在执行3次
主进程正在执行4次
主进程正在执行5次
主进程正在执行6次
主进程正在执行7次
主进程正在执行8次
主进程正在执行9次
主进程正在执行10次
主进程正在执行11次
主进程正在执行12次
主进程正在执行13次
主进程正在执行14次
主进程正在执行15次
主进程正在执行16次
主进程正在执行17次
主进程正在执行18次
主进程正在执行19次
主进程正在执行20次

 


在join(millis)里添加时间参数: 

Java常用工具类--多线程_第15张图片

测试代码:

package com.imooc.join;

class MyThread extends Thread {
	public void run() {
		for (int i = 1; i < 2000; i++) {
			System.out.println(getName() + "正在执行" + i + "次");
		}

	}

}

public class JoinDemo {

	public static void main(String[] args) {
		MyThread mt = new MyThread();
		mt.start();
		try {
			mt.join(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		for (int i = 1; i < 21; i++) {
			System.out.println("主进程" + "正在执行" + i + "次");
		}
	}

}

输出结果:会在运行1毫秒之后,让出cpu给其他进程
 

Java常用工具类--多线程_第16张图片


线程的优先级:
 

Java常用工具类--多线程_第17张图片

Java常用工具类--多线程_第18张图片

Java常用工具类--多线程_第19张图片

测试代码:

package com.imooc.priority;

class MyThread extends Thread {
	private String name;

	public MyThread(String name) {
		this.name = name;
	}

	public void run() {
		for (int i = 1; i <= 10; i++) {
			System.out.println("线程正在运行" + name + "  " + i);
		}
	}

}

public class Priority {

	public static void main(String[] args) {
		// 获取主线程优先级
		int mainPriority = Thread.currentThread().getPriority();
		System.out.println("主线程的优先级:" + mainPriority);
		
		MyThread mt1 = new MyThread("线程XXX");
		mt1.setPriority(1);
		mt1.start();
		System.out.println("线程XXX的优先级:" + mt1.getPriority());
		
		MyThread mt = new MyThread("线程SSS");
//		mt.setPriority(10);
		mt.setPriority(Thread.MAX_PRIORITY);
		mt.start();
		System.out.println("线程SSS的优先级:" + mt.getPriority());

	}

}

输出结果:
虽然优先级高,但是也并不能保证可以优先执行,具体情况具体分析

主线程的优先级:5
线程XXX的优先级:1
线程SSS的优先级:10
线程正在运行线程XXX  1
线程正在运行线程XXX  2
线程正在运行线程SSS  1
线程正在运行线程XXX  3
线程正在运行线程XXX  4
线程正在运行线程XXX  5
线程正在运行线程XXX  6
线程正在运行线程XXX  7
线程正在运行线程XXX  8
线程正在运行线程XXX  9
线程正在运行线程XXX  10
线程正在运行线程SSS  2
线程正在运行线程SSS  3
线程正在运行线程SSS  4
线程正在运行线程SSS  5
线程正在运行线程SSS  6
线程正在运行线程SSS  7
线程正在运行线程SSS  8
线程正在运行线程SSS  9
线程正在运行线程SSS  10

线程同步:

Java常用工具类--多线程_第20张图片

synchronized关键字保证共享对象在同一时刻只能被一个线程访问,但它不能保证多个线程可以同时执行和结束 

Java常用工具类--多线程_第21张图片

Java常用工具类--多线程_第22张图片

案例:
Bank类:

package com.imooc.bank;

public class Bank {
	private String account;// 账号
	private int balance;// 账户余额

	// 无参构造
	public Bank() {

	}

	// 带参构造
	public Bank(String account, int balance) {
		this.account = account;
		this.balance = balance;
	}

	// setter getter
	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;
	}

	public int getBalance() {
		return balance;
	}

	public void setBalance(int balance) {
		this.balance = balance;
	}

	// 重写toString()
	@Override
	public String toString() {
		return "Bank [账号:" + account + ", 余额:" + balance + "]";
	}

	// 存款,加上synchronized,保证执行这个的线程不允许被打断
	public synchronized void saveAccount() {
		int balance = getBalance();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// 修改余额+100
		balance += 100;
		setBalance(balance);
		System.out.println("存款后账户余额为:" + balance);
	}

	// 取款
	public void drawAccount() {
		synchronized (this) {
			int balance = getBalance();
			// 修改余额-200
			balance = balance - 200;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			setBalance(balance);
			System.out.println("取款后账户余额为:" + balance);
		}
	}

}

SaveAccount类:

package com.imooc.bank;

public class SaveAccount implements Runnable {
	Bank bank;

	public SaveAccount(Bank bank) {
		this.bank = bank;
	}

	@Override
	public void run() {
		bank.saveAccount();

	}

}

DrawAccount类:

package com.imooc.bank;

public class DrawAccount implements Runnable {
	Bank bank;

	public DrawAccount(Bank bank) {
		this.bank = bank;
	}

	@Override
	public void run() {
		bank.drawAccount();

	}

}

测试代码:

package com.imooc.bank;

public class Test {

	public static void main(String[] args) {
		// 创建账户,余额为1000
		Bank bank = new Bank("1001", 1000);
		// 创建线程对象
		SaveAccount sa = new SaveAccount(bank);
		DrawAccount da = new DrawAccount(bank);
		Thread save = new Thread(sa);
		Thread draw = new Thread(da);

		save.start();
		draw.start();
		try {
			draw.join();
			save.join();

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		System.out.println(bank);

	}

}

输出结果:

存款后账户余额为:1100
取款后账户余额为:900
Bank [账号:1001, 余额:900]

 


线程间通信:

Java常用工具类--多线程_第23张图片

 

Java常用工具类--多线程_第24张图片

案例:生产者消费者

Queue类:

package com.imooc.queue;

public class Queue {
	int n;
	boolean flag = false;

	public synchronized int get() {
		if (!flag) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("消费:" + n);
		flag = false;//消费完毕,容器中没有数据
		notifyAll();//唤醒所有线程,结束死锁
		return n;
	}

	public synchronized void set(int n) {
		if(flag) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("生产:" + n);
		this.n = n;
		flag = true;//生产完毕,容器里已经有数据
		notifyAll();//唤醒所有线程,结束死锁
	}

}

Producer类:

package com.imooc.queue;

public class Producer implements Runnable{
	Queue queue;
	public Producer(Queue queue) {
		this.queue = queue;
	}
	@Override
	public void run() {
		int i =0;
		while(true) {
			queue.set(i++);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
	}

}

Consumer类:
 

package com.imooc.queue;

public class Consumer implements Runnable{
	Queue queue;
	public Consumer(Queue queue) {
		this.queue = queue;
	}
	@Override
	public void run() {
		while(true) {
			queue.get();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

测试代码:

package com.imooc.queue;

public class Test {

	public static void main(String[] args) {
		Queue queue = new Queue();
		new Thread(new Producer(queue)).start();
		new Thread(new Consumer(queue)).start();

	}

}

输出结果:会无限循环

生产:0
消费:0
生产:1
消费:1
生产:2
消费:2
生产:3
消费:3
生产:4
消费:4
生产:5
消费:5
生产:6
消费:6

总结:

Java常用工具类--多线程_第25张图片

Java常用工具类--多线程_第26张图片

Java常用工具类--多线程_第27张图片

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Java零基础入门)