多线程
进程:系统资源分配的单位(CPU、磁盘、内存、网络)
线程:独立调度和分配的基本单位,共享进程资源
多线程:一个进程包含多个线程,用来完成不同的工作
进程是为了提高系统资源的利用率和系统吞吐量
线程是为了减少程序在并发执行时付出的时空开销
线程的使用
- 继承Thread类
- 实现Runnable接口
继承Thread类
构造方法
Thread() #分配一个新的 Thread对象
Thread(String name) #分配一个新的 Thread对象
常用方法
void run() #如果该线程是使用一个单独的 Runnable运行对象的构造,然后 Runnable对象的 run方法被调用;否则,该方法不返回
void start() #导致该线程开始执行;java虚拟机调用这个线程的 run方法
声明方式
public class 线程类名 extends Thread{
//重写run方法
public void run(){
}
}
实现Runnable接口
声明方式
public class 线程名 implements Runnable{
//实现run方法
public void run(){
}
}
线程的优先级
默认的线程优先级为5
线程优先级最高为10
线程优先级最低为1
线程优先级指的是一种概率
守护线程
用户线程:User Thread
守护线程:Daemon Thread,主要为其他线程提供服务的,比如垃圾回收线程
守护线程主要是在用户线程都执行玩的情况下执行,如果没有用户线程执行,守护线程自动退出
UserThread类
package com.Thread.util;
/*
* @author Administrator
* @version 1.0
*/
public class UserThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "--->" + i);
}
}
}
DaemonThread类
package com.Thread.util;
/*
* @author Administrator
* @version 1.0
*/
public class DaemonThread implements Runnable {
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是守护进程,守护到永远");
}
}
}
ThreadDemo类
package com.Thread.util;
/*
* @author Administrator
* @version 1.0
*/
public class ThreadDemo {
//主函数
public static void main(String[] args){
//初始化用户线程
UserThread userThread = new UserThread();
Thread user = new Thread(userThread);
//设置用户线程的名字
user.setName("用户线程");
//初始化守护线程
DaemonThread daemonThread = new DaemonThread();
Thread daemon = new Thread(daemonThread);
//设置线程为守护线程
daemon.setDaemon(true);
//设置守护线程的名字
daemon.setName("守护线程");
//启动线程
user.start();
daemon.start();
//我是守护进程,守护到永远
//用户线程--->i
}
}
线程的同步
(1)同步代码块
synchronized (对象) {
}
(2)同步方法
synchronized修饰的方法
(3)互斥锁
Lock,保证数据的完整性
ReentrantLock类
构造方法
ReentrantLock() #创建 ReentrantLock实例
常用方法
void lock() #获取锁
void unlock() #试图释放这个锁
多线程卖票示例
Ticket类
package com.Thread.util;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
* @author Administrator
* @version 1.0
*/
public class Ticket implements Runnable{
//定义成员变量
private int total;
//向上转型
private Lock lock = new ReentrantLock();
//无参构造方法
public Ticket(){
}
//有参构造方法
public Ticket(int total){
this.total = total;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public synchronized void saleTicket(){
total--;
System.out.println(Thread.currentThread().getName() + "卖了1张票,还剩" + total + "张票");
}
//方法一,同步代码块,同步代码块是一种高开销,尽量减少同步代码块的内容
@Override
public void run() {
while (total > 0){
//锁机制
synchronized (this) {
total--;
String window = Thread.currentThread().getName();
System.out.println(window + "卖了1张票,还剩" + total + "张票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//方法二,同步方法
// @Override
// public void run() {
// while (total > 0){
// //锁机制
// saleTicket();
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }
//方法三,互斥锁
// @Override
// public void run() {
// while (total > 0){
// try {
// lock.lock();
// total--;
// String window = Thread.currentThread().getName();
// System.out.println(window + "卖了1张票,还剩" + total + "张票");
// } finally {
// lock.unlock();
// }
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }
}
SaleTicket类
package com.Thread.util;
/*
* @author Administrator
* @version 1.0
*/
public class SaleTicket {
//主函数
public static void main(String[] args) {
//初始化Ticket对象
Ticket ticket = new Ticket(10);
//初始化Thread对象
Thread window1 = new Thread(ticket);
window1.setName("窗口1");
Thread window2 = new Thread(ticket);
window2.setName("窗口2");
//启动线程
window1.start();
window2.start();
}
}
线程的等待与唤醒
wait:线程等待,知道另一个线程调用该对象的notify()方法或notifyAll()方法
notify:唤醒正在等待对象监视器的单个线程
notifyAll:唤醒正在等待对象监视器的所有线程
sleep:睡眠时间,Thread自带的方法
实现线程的等待与唤醒
(1)匿名内部类
package com.Thread.util;
/*
* @author Administrator
* @version 1.0
*/
public class WaitNotify {
//定义静态成员变量
private static Object object = new Object();
//匿名内部类创建唤醒线程
private static Thread notify = new Thread(){
@Override
public void run() {
synchronized (object){
object.notify();
System.out.println(Thread.currentThread().getName() + "调用了notify方法");
}
System.out.println(Thread.currentThread().getName() + "释放了锁");
}
};
//匿名内部类创建等待线程
private static Thread wait = new Thread(){
@Override
public void run() {
synchronized (object){
try {
object.wait();
System.out.println(Thread.currentThread().getName() + "在等待");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "被唤醒,获得了锁");
}
}
};
//主函数
public static void main(String[] args) {
//设置线程的名字
wait.setName("等待线程");
notify.setName("唤醒线程");
//启动线程
wait.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
notify.start();
}
}
(2)静态内部类
package com.Thread.util;
/*
* @author Administrator
* @version 1.0
*/
public class ThreadDemo {
//定义静态成员变量
private static Object object = new Object();
//静态内部类
static class Thread1 implements Runnable{
@Override
public void run() {
synchronized (object){
object.notify();
System.out.println(Thread.currentThread().getName() + "调用了notify方法");
}
System.out.println(Thread.currentThread().getName() + "释放了锁");
}
}
//静态内部类
static class Thread2 implements Runnable{
@Override
public void run() {
synchronized (object){
try {
object.wait();
System.out.println(Thread.currentThread().getName() + "在等待");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "被唤醒,获得了锁");
}
}
}
//主函数
public static void main(String[] args) {
//初始化静态对象
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
//初始化等待和唤醒线程
Thread notify = new Thread(thread1);
Thread wait = new Thread(thread2);
//设置线程的名字
wait.setName("等待线程");
notify.setName("唤醒线程");
//启动线程
wait.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
notify.start();
}
}
线程池
概述
多个线程运行时运行机制,包括排队策略,包括线程存活时间,框架策略,管理,创建,释放
构造方法
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) #创建具有给定的初始参数和默认线厂和拒绝执行处理程序的一个新的 ThreadPoolExecutor
corePoolSize:核心池
maximumPoolSize:线程池最大线程数
keepAliveTime:线程没有任务执行时,最多多长时间会终止。大于corePoolSize才起作用
TimeUnit :keepAliveTime的时间单位
workQueue:用于存放待执行的任务(ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等)
常用方法
void execute(Runnable command) #在未来的某个时候执行给定的任务
void submit(Runnable task) #一个即将完成的任务的未来
void shutdown() #启动一个有序的关机,在以前提交的任务被执行,但没有新的任务将被接受
List<Runnable> shutdownNow() #试图阻止所有积极执行任务,停止等待任务的处理,并返回一个列表,正在等待执行的任务
MyTask类
package com.Thread.util;
/*
* @author Administrator
* @version 1.0
*/
public class MyTask implements Runnable{
//工作任务数
private int taskNum;
//无参构造方法
public MyTask(){
}
//有参构造方法
public MyTask(int taskNum){
this.taskNum = taskNum;
}
@Override
public void run() {
System.out.println("正在执行的任务" + taskNum);
try {
Thread.sleep(2000);
System.out.println("task" + taskNum + "finished!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int getTaskNum() {
return taskNum;
}
public void setTaskNum(int taskNum) {
this.taskNum = taskNum;
}
}
ThreadPoolTest类
package com.Thread.util;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/*
* @author Administrator
* @version 1.0
*/
public class ThreadPoolTest {
//主函数
public static void main(String[] args) {
//初始化线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,15,1000, TimeUnit.MICROSECONDS,new ArrayBlockingQueue<Runnable>(5)
);
//模拟线程的工作机制
for (int i = 0; i < 20; i++) {
//新建一个任务
MyTask myTask = new MyTask(i);
//往线程中添加任务
threadPoolExecutor.execute(myTask);
System.out.println("线程池中的线程数目:"+threadPoolExecutor.getPoolSize()+"队列中等待的任务数"+threadPoolExecutor.getQueue()
+"已执行完成的任务数目"+threadPoolExecutor.getCompletedTaskCount());
}
//关闭线程池
threadPoolExecutor.shutdown();
}
}