进程与线程
进程
进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
线程
线程是一条执行路径,是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
多线程实现方式
Thread类
为什么多线程的启动不直接使用run()方法而必须使用Thread类中的start()方法呢?
run()和start()的区别可以用一句话概括:单独调用run()方法,是同步执行;通过start()调用run(),是异步执行。
Runnable接口
Lamda和Runnable的结合使用
public class ThreadDemo {
public static void main(String[] args) {
for (int x=0;x<3;x++){
String title = "线程对象-"+ x ;
Runnable run = ()->{
for (inty=0;y<10;y++){
System.out.println(title +“运行,y ="+ y);
}
};
new Thread(run).start();
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
for (intx=0;x<3;x++) {
String title = "线程对象-"+ x ;
new Thread(()-> {
for (int y =0;y<10;y++) {
System. out. println(title + "运行,y ="+y )
}
}).start();
}
}
Callable接口(带有返回值)
class MyThread implements Cal1able<String> {
@Override
public String ca1l() throws Exception {
for(intX=0;x<10;x++){
System. out . print1n("*********线程执行、X = "+ x);
}
return "线程执行完毕";
}
}
public class ThreadDemo {
public static void main(String[ ] args) throws Exception {
FutureTask<String> task = new FutureTask<> (new MyThread( )) ;
new Thread(task) .start();
System. out. println(" [线程返回数据]”+ task.get());
}
}
请解释Runnable与Callable的区别?
Runnable是在JDK1.0的时候提出的多线程的实现接口,而Callable是在JDK1.5之后提出的;
java.lang.Runnable接口之中只提供有一个run()方法,并且没有返回值;
java.util.concurrent.Callable 接口提供有 callO)方法,可以有返回值。
多线程运行状态
新生状态
创建线程对象进入新生状态;
就绪状态
进入就绪状态的三种情况:
当线程对象调用start()方法是由新生状态进入就绪状态;
由阻塞状态转入就绪状态;
如果CPU将本地线程切换成其它线程,本地线程回到就绪状态。
运行状态:
只能通过CPU调度由就绪状态进入运行状态;
阻塞状态:
- sleep():通过调用方法进入休眠,在休眠期满之后,该线程不一定立即执行,因为其它线程可能正在执行,除非该线程有较高的优先级;
- wait():通过调用方法进入等待,它与sleep()之间的区别在于对象锁是否释放;需要调用notify()方法来唤醒线程;
- 挂起:由于某种异常情况,临时停止或中断线程的执行时,线程就处于挂起状态,需要恢复回到就绪状态;
- IO阻塞中断:通讯过程中数据中断。
死亡状态:
通过线程本身自然死亡;
强行结束,通过加入一个标识控制线程里的循环,写一个专门停止的方法,想停止就调用。
public class ThreadDemo {
public static boolean fLag = true ;
public static void main(String[] args) throws Exception {
new Thread(() -> {
long num = 0;
while (fLag) {
try {
Thread.sLeep(50);
} catch (InterruptedException e) {
e. printStackTrace();
}
System.out.println(Thread.current Thread( ).getName() +“正在运行、num = " + num++);
}
},"执行线程").start();
Thread.sleep(200); // 运行2θ0毫秒
fLag = false ; //停止线程
}
}
线程常用操作方法
线程的命名和取得
多线程的运行状态是不确定的,那么在程序的开发之中为了可以获取到一些需要使用到的线程就只能依靠线程的名字进行操作。
构造方法: public Thread(Runnable target, String name);
设置名字: public final void setName(String name);。
取得名字: public final String getName( );
线程休眠(不释放对象锁)
使某一个线程暂缓处理,使用休眠处理:
休眠: public static void sleep(long millis) throws InterruptedException;
休眠: public static void sleep(long millis, int nanos) throws InterruptedExcept
线程中断
线程的休眠里面提供有一个中断异常,实际上就证明线程的休眠是可以被打断的,在Thread类里面提供有这种中断执行的处理方法。
所有正在执行的线程都是可以被中断的,中断线程必须进行异常的处理。
判断线程是否被中断: public boolean isInterrupted;
中断线程执行:public void interrupt;
线程强制运行
在线程操作中,可以使用 join() 方法让一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后才可以继续执行。
在进行线程的强制执行要先获取强制执行线程的对象之后才可以执行join()。
public class ThreadDemo {
public static void main(String[ ] args ) throws Exception {
Thread mainThread=Thread.currentThread() //获取主线程
Thread thread = new Thread(() -> {
for(intx=0;x<100;x++){
if(x==3){
mainThread.join();
}
System.out.println(Thread. currentThread(). getName() + "执行、X ="+ x);
}
}, "玩耍的线程") ; I
thread.start();
for(intX=0;x<100;x++){
System.out.print1n(" [霸道的main线程] number = " + x);|
}
}
线程的礼让
线程的礼让是先将资源让出去让别的线程先执行,可以使用Thread中提供的方法,礼让执行的时候每调用一次yield()方法只会礼让一次当前资源。
public class ThreadDemo {
public static void main(String[ ] args ) throws Exception {
Thread thread = new Thread(() -> {
for(intx=0;x<100;x++){
if(x%3==0){
thread .yield();
}
System.out.println(Thread. currentThread(). getName() + "执行、X ="+ x);
}
}, "玩耍的线程") ; I
thread.start();
for(intX=0;x<100;x++){
System.out.print1n(" [霸道的main线程] number = " + x);|
}
}
线程优先级
从理论上来讲线程的优先级越有可能先执行(越有可能先抢占资源)
主线程的优先级:中等优先级;
创建的线程默认的也是中等优先级。
设置优先级:public final void setPriority(int newPriority)
获取优先级:public final int getPriority
最高优先级: public static final int MAX PRIORITY、10;
中等优先级: public static final int NORM PRIORITY、5;
最低优先级: public static final int MIN PRIORITY、1;