JavaSE多线程
1、进程与线程
进程与线程区别: 本质区别在于,每个进程拥有自己的一整套变量,而线程则共享数据。共享变量使得线程之间的通信比进程之间的通信更有效、更方便。
线程状态:
2、java多线程实现
java线程创建调用流程
- 继承Thread类实现多线程
package test;
class MyThread extends Thread{
private String title;
public MyThread(String title){
this.title = title;
}
@Override
public void run() {
for (int i=0; i<10; i++){
System.out.println(this.title+", i = "+i);
}
}
}
public class TestDemo {
public static void main(String[] args) {
MyThread myThread1 = new MyThread("thread1");
MyThread myThread2 = new MyThread("thread2");
MyThread myThread3 = new MyThread("thread3");
myThread1.start();
myThread2.start();
myThread3.start();
}
}
- Runnable()接口实现多线程(更好的描述程序共享)
package test;
class MyThread implements Runnable{
private String title;
public MyThread(String title){
this.title = title;
}
@Override
public void run() {
for (int i=0; i<10; i++){
System.out.println(this.title+", i = "+i);
}
}
}
public class TestDemo {
public static void main(String[] args) {
MyThread myThread1 = new MyThread("thread1");
MyThread myThread2 = new MyThread("thread2");
MyThread myThread3 = new MyThread("thread3");
new Thread(myThread1).start();
new Thread(myThread2).start();
new Thread(myThread3).start();
}
}
注意: Runnable接口对象可以采用匿名内部类或者Lambda表达式来定义
/**
* 使用匿名内部类创建线程
*/
//public class TestDemo {
// public static void main(String[] args) {
// new Thread(new Runnable() {
// @Override
// public void run() {
// System.out.println("Hello World");
// }
// }).start();
// }
//}
/**
* 使用Lambda表达式创建线程
*/
public class TestDemo {
public static void main(String[] args) {
Runnable runnable = () -> {
System.out.println("Hello World");
};
new Thread(runnable).start();
}
}
-
Thread和Runnable的关系
Thread代理类
MyThread真实类
多线程的设计中,使用了代理设计模式的结构,用户自定义的线程主体负责项目核心功能的实现,辅助实现通过Thread类实现. 在进行Thread启动多线程的时候调用的是start()方法,而后找到run()方法;但通过Thread的构造方法传递Runnable接口对象的时候,该接口对象被Thread类中的target属性保存,start()方法执行调用Thread中的run()方法,该run()方法调用Runnable接口子类对象的run()方法。 多线程开发的本质在于多个线程可以进行同一资源的抢占。
-
Callable实现多线程
import java.util.concurrent;
class MyThread implements Callable<String>{
private int ticket = 10;
@Override
public String call() throws Exception{
while(ticket>0){
System.out.println("剩余票数:" + this.ticket--);
}
return "票卖完了";
}
}
public class TestDemo{
public static void main(String[] args) {
FutureTask<String> task = new FutureTask<>(new MyThread());
new Thread(task).start();
new Thread(task).start();
try {
System.out.println(task.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
- 解释Runnable与Callable的区别?
- Runnable是jdk1.0的实现接口;Callable是jdk1.5的实现接口
- java.lang.Runable接口之中只提供一个run()方法,并且没有返回值
- java.util.concurrent.Callable接口提供有call()方法,可以有返回值
3、线程常用操作方法
定义在Thread中
-
线程的命名和取得
- 构造方法 public Thread(Runnable target, String name);
- 设置名字 public final void setName(String name);
- 取得名字 public final String getName();
- 获取当前线程 public static Thread currentThread();
每一个JVM进程都会有线程
主线程负责整体流程,而子线程负责处理耗时操作
主线程可以创建若干个子线程
-
线程的休眠
某个线程暂缓执行
public static void sleep(long millis) throws InterruptedException public static void sleep(long millis, int nanos) throws InterruptedException 参数 millis - 以毫秒为单位的睡眠时间长度 nanos - 0-999999额外的纳秒睡眠 休眠期间产生中间异常
-
产生多个线程进行休眠
package com.yrd.myThread; public class ThreadDemo { public static void main(String[] args) { for (int num = 0; num < 5; num++){ new Thread(()->{ for (int x=0; x<10; ++x){ System.out.println(Thread.currentThread().getName() + "x = " + x); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }, "线程对象" + num).start(); } } }
-
-
线程中断
线程休眠可以被打断,Thread里面提供的终端执行的处理方法:
- 判断线程是否被执行:public boolean isInterrupted()
- 中断线程执行:public void Interrupt()
-
线程强制执行
当满足某些条件之后,某一个线程对象可以一直独占资源,一直到任务结束
- 强制执行 public final void join() throws InterruptedException
-
线程礼让 public static void yield()
-
线程优先级
线程的优先级越高越有可能先执行(越有可能抢占资源)
- 设置优先级 public final void setPriority(int newPriority)
- MIN_PRIORITY = 1
- MAX_PRIORITY = 10
- NORM_PRIORITY = 5
- 获取优先值
- public final int getPriority()
- 设置优先级 public final void setPriority(int newPriority)
4、线程的同步和死锁
多线程处理中利用Runnable描述多个线程操作的资源,Thread描述线程对象,多个线程访问同一资源时处理不当会发生数据错误
-
同步处理
-
线程死锁