Java 多线程
一、什么是多线程
如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”。
多个线程交替占用CPU资源,而非真正的并行执行。
二、多线程好处
充分利用CPU的资源。
简化编程模型。
带来良好的用户体验。
三、Thread类
方法 | 功能 |
---|---|
getName() | 返回该线程的名称。 |
getPriority() | 返回线程的优先级。 |
字段 | 功能 |
---|---|
MAX_PRIORITY | 线程可以具有的最高优先级。 |
MIN_PRIORITY | 线程可以具有的最低优先级。 |
NORM_PRIORITY | 分配给线程的默认优先级。 |
public static void main(String[] args) {
Thread thread = new Thread();
String name = thread.getName();
System.out.println(name);
int priority = thread.getPriority();
System.out.println("当前线程的优先级:" + priority);
thread.setName("尼古拉斯赵四");
System.out.println("线程名称:" + thread.getName());
thread.setPriority(8);
System.out.println("线程优先级:"+thread.getPriority());
System.out.println("线程优先级最高值:" + Thread.MAX_PRIORITY);
System.out.println("线程优先级最低值:" + Thread.MIN_PRIORITY);
System.out.println("线程优先级默认值:" + Thread.NORM_PRIORITY);
}
四、创建线程
1. 继承java.lang.Thread类
//一个类要定义成线程类,可以通过继承Thread类来实现,然后重写Thread类里的run()方法
public class MyThread extends Thread {
public MyThread(){}
public MyThread(String name){
super(name);
}
@Override
public void run() {
//在重写的run()方法中编写你要执行的代码:使用循环输出1-20
for (int i = 1; i <=20; i++) {
System.out.println(Thread.currentThread().getName()+"》"+i);
}
}
}
public class Test {
public static void main(String[] args) {
// 创建线程类对象
MyThread mt1 = new MyThread("天山童姥");
MyThread mt2 = new MyThread("逍遥子");
// mt1.run();
// start()方法是启动线程的方法
mt1.start();
mt2.start();
// 当同时启动两个线程以后,会出现两个线程交替占用CPU执行代码的结果
}
}
2. 实现java.lang.Runnable接口
public class MyThread implements Runnable {
@Override
public void run() {
// 在重写的run()方法中编写你要执行的代码:使用循环输出1-20
for (int i = 1; i <= 20; i++) {
System.out.println(Thread.currentThread().getName() + "》" + i);
}
}
}
public class Test {
public static void main(String[] args) {
MyThread mt1 = new MyThread();
Thread thread1 = new Thread(mt1, "千里眼");
Thread thread2 = new Thread(mt1, "顺风耳");
/*
* start()方法是Thread类中的方法,而我们需要通过start()方法来调用run()方法,不能直接调用run()方法
* 但是Runnable接口中只有一个抽象方法run()方法,那么实现Runnable接口的类不能调用start()方法
* 解决办法:
* 将实现Runnable接口的类对象作为参数传递给Thread构造方法,然后通过Thread类对象调用start()方法
*/
// mt1.start();
thread1.start();
thread2.start();
}
}
五、常用方法
方 法 | 说 明 |
---|---|
void setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程 |
boolean isAlive() | 测试线程是否处于活动状态 |
1. sleep():线程休眠
public class Wait {
public static void bySec(long s) {
for (int i = 0; i < s; i++) {
System.out.println(i + 1 + "秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2. join():强势运行
public static void main(String[] args) {
Thread temp = new Thread(new MyThread());
temp.start();
for(int i=0;i<20;i++){
if(i==5){
try {
temp.join();
} catch (InterruptedException e) {
e.printStackTrace(); }}
System.out.println(Thread.currentThread().getName()+"运行:"+i);
}
//省略代码…
}
3. yield():礼让
public class MyThread implements Runnable{
public void run(){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"正在运行:"+i);
if(i==3){
System.out.print("线程礼让:");
Thread.yield();
}
}
}
}
六、同步方法
使用synchronized修饰的方法控制对类成员变量的访问(synchronized就是为当前的线程声明一把锁)
1. 方法
访问修饰符 synchronized 返回类型 方法名(参数列表){……}
或
synchronized 访问修饰符 返回类型 方法名(参数列表){……}
2. 静态代码块
使用synchronized关键字修饰的代码块。
synchronized(syncObject){
//需要同步的代码
}
3. syncObject为需同步的对象
通常为this,效果与同步方法相同。
public void run() {
while (true) {
synchronized (this) { //同步代码块
// 省略修改数据的代码......
// 省略显示信息的代码......
}
}
}
public class Piao implements Runnable {
// 声明一个变量用来表示票库中票的数据
public int num = 10;
// 声明一个变量用来表示用户抢到了第几张票
public int count = 0;
@Override
public void run() {
while (true) {
synchronized (this) {
// 当票库里的票<0的时候,不再进行循环
if (num <= 0) {
break;
}
num--;
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "抢到了第" + count + "张票,还剩下" + num + "张票");
}
}
}
}