文章目录
1 创建多线程的几种方式
线程的创建常用的几种方式:
- 创建一个Thread类或者一个Thread子类的对象。
- 创建一个实现Runnable接口的类的对象。
1.1 通过Thread类创建线程
1.1.1 Thread类
首先来看下Thread类:Thread是一个线程类,位于java.lang包下。
Thread类的常用方法:
1.1.2 创建线程
通过继承Thread类的方式创建线程类,重写run()方法。
示例代码如下:
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();//启动线程
}
}
1.2 实现Runnable接口创建线程
1.2.1 Runnable接口介绍
Runnable接口:
- 只有一个方法run()。
- Runnable是Java中用以实现线程的接口。
- 任何实现线程功能的类都必须实现该接口。
为什么要实现Runnable接口?
- Java不支持多继承。
- 不打算重写Thread类的其他方法。
下面看一下示例代码:
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();
}
}
2 线程的状态
2.1 线程的状态
下面看一下线程都具有哪些状态:
- 新建(New)
- 可运行(Runnable)
- 正在运行(Running)
- 阻塞(Blocked)
- 终止(Dead)
如下为线程的状态转换图:
2.2 sleep方法
下面看一下sleep方法:
作用:在指定的毫秒数内让正在执行的线程休眠(暂停执行),参数为休眠的时间,单位是毫秒。
2.3 join方法
首先看下无参函数:
- 作用是等待调用该方法的线程结束后才能执行,就是说某个线程调用的这个方法,那么其他线程必须等到这个方法执行完才能执行。
下面看下带参的函数:
- 等待该线程终止的最长时间为millis毫秒,如果millis为0则意味着要一直等下去。
2.4 线程优先级
线程优先级简介:
- Java为线程类提供了10个优先级。
- 优先级可以用整数1-10表示,超过范围会抛出异常。
- 主线程默认优先级为5。
- 优先级常量:
- MAX_PRIORITY:线程的最高优先级10
- MIN_PRIORITY:线程的最低优先级1
- NORM_PRIORITY:线程的默认优先级5
3 线程间同步
先来看下多线程运行问题:
- 各个线程是通过竞争CPU时间而获得运行机会的
- 各线程什么时候得到CPU时间,占用多久,是不可预测的
- 一个正在运行着的线程在什么地方被暂停是不确定的
下面看下银行存取款问题:
- 为了保证在存款或取款的时候,不允许其他线程对帐户余额进行操作
- 需要将Bank对象进行锁定
- 使用关键字synchronized实现
具体的代码就不贴了,下面看下synchronized关键字的使用,synchronized关键字用在:
- 成员方法
- 静态方法
- 语句块
语句块时如下:
4 线程间通信
先看下线程间通信可以使用的几个方法:
- wait()方法:中断方法的执行,使线程等待。
- notify()方法:唤醒处于等待的某一个线程,使其结束等待。
- nofifyAll()方法:唤醒所有处于等待的线程,使它们结束等待。
下面以生产者消费者为例简单的演示下java中的线程间通信:
Queue.java:
package com.imooc.queue;
public class Queue {
private 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();
}
}
Consumer.java:
package com.imooc.queue;
public class Consumer implements Runnable{
Queue queue;
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();
}
}
}
}
Producer.java:
package com.imooc.queue;
public class Producer implements Runnable{
Queue queue;
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();
}
}
}
}
Test.java:
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();
}
}