什么是多线程
线程是比进程还要小的运算单位,一个进程包含多个线程(线程可以看做一个子程序)
通过对CPU的轮转来达到多个线程的同时运行
线程的创建
1.创建一个Thread类,或者一个Thread子类对象
- Thread是一个线程类,位于java.lang包下
构造方法 | 说明 |
---|---|
Thread() | 创建一个线程对象 |
Thread(String name) | 创建一个具有指定名称的线程对象 |
Thread(Runnable target) | 创建一个基于Runnable接口实现类的线程对象 |
Thread(Runnable target,string name) | 城建一个基于Runnable接口实现类,并且有指定名称的线程对象 |
- Thread类的常用方法
方法 说明 public void run() 线程相关的代码写在该方法中,一般需要方法重写 public void start() 启动线程的方法 public static void sleep(long m) 线程休眠m毫秒的方法 public void join() 有限执行调用join()方法的线程(抢占资源)
2.创建一个实现Runnable接口的类的对象
- 只有一个方法run()
- Runnable是java中用以实现线程的接口
- 任何实现线程功能的类都必须实现该接口
线程创建
- 通过继承Thread类的方式创建线程类,重写run()方法
package Thread1;
class Thread extends java.lang.Thread{
public Thread(String name){
super(name);
}
public void run(){
for (int i = 0; i <10000 ; i++) {
System.out.println(getName()+"运行"+i);
}
}
}
public class MyThread {
public static void main(String[] args) {
Thread mt1 = new Thread("线程1");//创建线程1
Thread mt2 = new Thread("线程2");//创建线程2
mt1.start();
mt2.start();
}
}
- 实现Runnable接口
class PrintRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
// 在Runnable接口中需要使用Thread.currentThread().getName()才能获取线程名
System.out.println(Thread.currentThread().getName()+"正在运行"+i);
}
}
}
public class Test {
public static void main(String[] args) {
/*
*1.创建Runnable接口的对象
*2.创建Thread类的对象,将Runnable类作为参数传入Thread
*3.使用Thread类调用start()函数启动线程
*/
PrintRunnable printRunnable = new PrintRunnable();
Thread thread = new Thread(printRunnable);
thread.start();
PrintRunnable printRunnable1 = new PrintRunnable();
Thread thread1 = new Thread(printRunnable1);
thread1.start();
}
}
线程的状态和生命周期
线程状态
1.新建(New)
2.可运行(Runnable) 该线程已经准备就绪
3.正在运行(Running) 获取了CPU的使用权
4.阻塞(Blocked)
5.终止(Dead)
生命周期
stop()函数在java中已经失效
sleep方法应用
public static void sleep(long millis)
- 是一个静态方法
- 作用:在指定的毫秒数内让正在执行的线程休眠(暂停执行)
- 参数为休眠时间,单位为毫秒
- 需要捕获一个异常
join方法应用
public final void join()
- 抢先运行
- 作用:等待调用该方法的线程结束后才能执行
- 需要捕获一个异常
public final void join(long millis)
- 作用:等待该线程终止的最长时间为millis毫秒,当等待时间用完,不管该线程是否运行完,其他线程都将执行
线程优先级
- Java为线程类提供了10个优先级(数字越大,表示的优先级越高)
- 优先级可以用整数1-10表示,超过范围会抛出异常
- 主线程默认优先级为5
- 优先级常量
- MAX_PRIORITY:线程的最高优先级10
- MIN_PRIORITY:线程的最低优先级1
- NORM_PRIORITY:线程默认优先级5
优先级相关方法
方法 | 说明 |
---|---|
public int getPriority() | 获取线程优先级的方法(返回的是一个整数) |
public void setPriority(int newPriority) | 设置线程优先级的方法 |
线程同步
多线程运行问题
- 各个线程是通过竞争CPU时间而获得运行的机会的
- 各线程什么时候得到CPU时间,占用多久,是不可预测的
- 一个正在运行着的线程在什么地方被暂停是不确定的
同步与死锁
- synchronized关键字用在
- 成员方法 public synchronized void saveAccount(){}
- 静态方法 public static synchronized void saveAccount(){}
- 语句块 synchronized(obj){…}
线程间的通信
- wait()方法:中断方法的执行,是线程等待
- notify()方法:唤醒处于等待的某一个线程,使其结束等待
- nofifyAll()方法:唤醒所有等待的线程,使他们结束等待
//Queue类
package queue;
public class Queue {
private int n ;
boolean flag=false;
public synchronized void setN(int n){
if(flag){
try{
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
notify();
}
flag=true;
System.out.println (" 生产"+n);
this.n = n;
}
public synchronized int getN(){
if (!flag){
try{
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
notify();
}
flag=false;
System.out.println("消费"+n);
return n;
}
}
//生产类
package queue;
public class Producer implements Runnable{
Queue queue;
Producer(Queue queue){
this.queue=queue;
}
@Override
public void run() {
int i=0;
while(true){
queue.setN(i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费类
package queue;
public class Consumer implements Runnable{
Queue queue;
Consumer(Queue queue){
this.queue=queue;
}
@Override
public void run() {
while(true){
queue.getN();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//测试类
package 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();
}
}