- 线程运行速度比进程速度快
实现多线程的3种方案
可以实现Thread类
-
任何情况下,只要定义了多线程,多线程的启动永远只有一种方案,Thread类中的start()方法
-
内部调用的是strat0(),这是一个JNI实现方法,JVM根据不同的系统实现不同的start0()方法
import java.util.function.*; 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 JavaDemo{ public static void main(String[] arges){ MyThread myThread01 = new MyThread("TEST01 "); myThread01.start(); MyThread myThread02 = new MyThread("TEST02 "); myThread02.start(); MyThread myThread03 = new MyThread("TEST03 "); myThread03.start(); } }
Runnable实现多线程
-
1.8之后就变为函数式接口,可以直接实现lambda函数式
-
开发中首要考虑Runnable实现,并通过Thread.start()方法
-
借助构造方法:public Thread(Runnable target)实现
- 这里是实现接口,所以MyThread可以作为一个正常的类,去继承其他类或是实现多个接口
import java.util.function.*;
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 JavaDemo{
public static void main(String[] arges){
Thread thread = new Thread(new MyThread("TEST"));
thread.start();
}
}
-
Lambda函数式(超简洁)
public class JavaDemo{ public static void main(String[] arges){ Runnable run = ()->{ System.out.println("这里在多线程中执行"); }; new Thread(run).start(); } }
#更简单的
import java.util.function.*;
public class JavaDemo{
public static void main(String[] arges){
new Thread(()->{
System.out.println("dsfsdf");
}).start();
}
}
Thread与Runnable的关系
- ````public class Thread extends Object implements Runnable{}```Thread类也是实现了Runnable接口的子类
- 有上面了解到,多线程的方法主要都是由Thread实现的,所以操作系统的资源调用也是通过Thread调用的
- Thread为代理类,MyThread或者实现Runnable接口的类为真实类
- 多线程开发的本质是在于多个线程可以进行对统一资源的抢占
Callable实现多线程
-
Runnable的缺点是,执行完毕后,无法给主线程一个返回值
-
1.5之后实现的新方法
java.util.concurrent.Callable
接口,使用泛型返回数据 -
方法流程图
Runnable与Callable
-
Runnable是在JDK1.0的时候提出的多线程的实现接口,而Callable是JDK1.5之后提出来的
-
java.lang.Runnable接口之中只提出一个run()方法,并没有返回值
-
java.util.concurrent.Callable接口提供有call()方法,可以有返回值;
import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; class MyThread implements Callable<String>{ @Override public String call() throws Exception{ for(int i=0;i < 1000;i++){ System.out.println("==========" + i); } return "=====end========"; } } public class JavaDemo{ public static void main(String[] arges)throws Exception{ FutureTask<String> task = new FutureTask<>(new MyThread()); new Thread(task).start(); System.out.println(task.get()); } }
其他小知识
多线程的状态
状态
- 创建
- start()
- 就绪状态
- 阻塞状态
- 运行状态
- 就绪状态
- 终止
进程与休眠
- 一个程序中可以启动若干个JVM,每个JVM就是一个进程
- 休眠可以设置为毫秒和纳秒2中精确度,如果被打断会抛出Exception子类的异常,必须处理
- 所有线程运行同一个方法时,也会有先后,并没有绝对的一起执行
线程的名称
-
开发为了获得一些线程的操作,可以通过线程的名称获得
- 构造方法:public Thread(Runnable target,String name)
- 设置名称:public final void setName(String name)
- 取的名称:public final String getName();
- 获得当前线程的方法:Thread.currentThread().getName()
线程中断
- 判断是否被中断:public boolean isInterrupted();//被中断 返回true
- 中断线程执行:public void interrupt();
线程的强制执行
public class test {
public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
Thread thread = new Thread(()->{
for (int x = 0; x < 100; x++){
if (x == 3){
try {
mainThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("thread == " + x);
}
});
thread.start();
for (int i = 0; i < 100; i++){
System.out.println("霸道主线程mainThread == " + i);
}
}
}
线程的礼让
-
礼让:public void yield()
-
每次出现竞争的时候,都会礼让一次,大部分时候会礼让,但是不明显
public static void main(String[] args) { Thread thread = new Thread(()->{ for (int x = 0; x < 100; x++){ if (x % 3 == 0){ Thread.yield(); System.out.println("===========我礼让一次==========="); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread == " + x); } }); thread.start(); for (int x = 0; x < 100; x++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("霸道主线程mainThread == " + x); } }
优先级设置
- 设置优先级:public final void setPriority(int new Priority);
- 默认优先级: 5(NORM_PRIORITY)
- 最高优先级:MAX_PRIORITY 10
- 中等优先级:NORM_PRIORITY 5
- 最低优先级:MIN_PRIORITY 1
- 获取优先级:public final int getPriority()
同步方法
同步代码块、同步方法
- 同步代码块,速度会变慢
线程的等待机制
- 死等:wait()
- 设定等待时间 wait(long timeout,int nanos)
- 唤醒第一个等待线程:notify()
- 唤醒全部线程:notifyALL()
- 禁用的方法:stop()、suspend()挂起、destroy()销毁
- 用全局变量去停止线程
守护线程
- 设置守护线程:public final void setDaemon(boolean on);
- 判断是否为守护线程:public final boolean isDaemon();
- 设置为守护线程后,整体程序结束后,守护线程也将结束
- JVM最大的守护线程就是GC线程,程序结束,GC也一起结束
volatile
正常的变量处理步骤:
- 获取变量原有的数据内容副本
- 利用副本为变量进行数学计算
- 将计算后的变量,保存到原始空间之中
volatile关键字
- 表示不使用副本,而是直接操作变量,所以并不是同步操作,也需要同步关键字
volatile与syncharoniaed的区别
- volaile主要在属性上使用,而synchronized是在代码块与方法上使用的
- volatile无法描述同步的处理,它只是一种直接内存的处理,避免的副本的操作,而synchronized是实现同步的
- volatile配送syncharoniaed处理同步,可以更快的运行
StringBuffer
-
线程安全的字符串添加方法,1.0之后提供的
-
追加:new StringBUffer(“www.cn”).insert(4,“mldn”)在第4个开始追加
-
部分删除:buf.append(“www.mldn.com”).delete(4,8).insert(4,“bridge”);//“www.bridge.com”
-
支付反转:buf.reverse()
-
StringBuilder:非线程安全的效率更高,1.5之后才提供的