进程与线程
引出:Dos系统中病毒死机——单进程
Windows多进程的处理方式,比如启动一个软件会在操作系统上分配一个进程。
进程和线程的关系,就是说,线城市进程的进一步划分,比如Word的拼写检查,在Word的进程中进行。如果一个线程没有了,拥有它的进程没有影响,而进程小时线程必定消失。
原本传统的进程任务是。一个程序独占所有属于该进程的文件、系统资源、IO装置,在多线程的进程中,多个线程程序在原本的程序位置运行,势必导致所有的线程共用一个资源(这里涉及到一定的安全性问题,后续研究。)
进程的系统资源是共享的,但是,程序处理需要CPU。对传统单核cup在同一个时间段。会有多个程序运行,但是一个时间点只有一个,所有程序要抢占CPU资源。
现在的多核CPU,此时可以清楚看见多线程是如何并发执行。
Java的多线程实现
两种方式:(java.lang 包下定义,lang包实实际运行中自动导入无需手工编写import语句)
A继承Tread类
B继承Runnable接口
一个类只要继承了Thread类,此类就称为多进程实现类,子类必须复写run方法。此方法是线程主体。
Class myThread extends Thread{
Private String name ;
Public myThread(String name){
This.name = name;
}
Public void run(){
For(int i = 1;i<100;i++){
System.out.println(name+”运行,i=”+i);
}
}
}
Public class ThreadDemo{
Public static void main(String[] args){
MyThread m1 = new mythread(“fghjk”);
MyThread m2 = new mythread(“fghjkvbnn”);
M1.run;
M2.run;
}
}
此时发现,县城其实并没有交错运行,说明此时线程并没有启动(线程的运 行需要本机底层操作系统的支持,start定义含有native关键词表示调用本 机的操作系统函数,重复调用start会抛出异常),如何启动?、
将上方的run都改成start(start中会调用run方法)
结果是随机的,哪个线程抢占了资源就能运行。
实现runnable接口
Class mythread implements runnable{
Private String name ;
Public myThread(String name){
This.name = name;
}
Public void run(){
For(int i = 1;i<100;i++){
System.out.println(name+”运行,i=”+i);
}
}
}//此时,runnable没有start来启动线程,还是依靠Thread
Public Class runnabledemo{
Public static void main(String[] args){
Mythread m1 = new mythread(_);
Mythread m2 = new mythread();
Thread t1 = new thread(m1);
Thread t2 = new thread(m2);
t1.run();
t2.run();
}
在Java中也可以通过实现runnable接口方式进行多线程实现。
Thread类和runnable接口都可以实现多线程,那么有什么分别?
Thread类也是runnable接口的子类,但在类中没有完全实现run’方法,仅仅调用了runnable中的方法,所以必须复写run方法。
使用上差别:继承了Thread的类不适合多个线程共享资源,而实现了runnable的类则可以方便的实现资源共享。
举例
public ststic viod main(String[] args){
Mytread m1 = new mythread();
Mythread m2 = new mythread();
M1.run();
M2.run();//m1.m2资源独立
}
public static void main(String[] args(){
mythread m = new mythread();
thread t1 = new thread(m);
thread t2 = new thread(m);
t1.run();
t2.run();//使用同一个资源m
}
故此runnable相对于Thread而言,有如下显著优势:
适合多个相同程序代码的线程去处理同一个资源的情况;
可以避免由于Java单继承特性带来的局限‘’
增强了程序的健壮性,代码能被多个线程共享,代码与数据是独立的
线程的状态
要想实现多线程,必须在主线程中实现建立新的线程的对象。任何线程具有5种状态:创建、就绪(start)、运行(start后自动调动run或者阻塞后手动进行run)、阻塞(sleep、suspend、wait)、终止(stop,或者run结束后的死亡状态,即使有资源不能运行)
操作线程的主要方法不在runnable中,而是在Thread里,eg:
currentThread表示返回当前执行的线程
getname返回线程的名字(在不起名时系统会自动设置一个名字在Thread类中有一个static的函数起名)
getpriority返回线程的优先级
isinterrupted判断线程是否被中断
isalive判断是否在活动
join throws interrupted exception 等待线程死亡
join (10000)throws interrupted exception等待毫秒后死亡
setname
setpriority设置优先级
sleep(10000)throws interrupted exception目前执行的线程休眠10000毫秒
tostring 返回代表县城的字符串
yield 将目前正在执行的线程暂停,允许其他线程运行
了解到一些方法比如suspend和resum以及过时,因为有死锁倾向
Runnable使用事例
再次调用run时。
待解决疑问:public static void main也是 一个线程,但是不调用run,main就不打印,调用了就打印???
梳理题:
1对Java程序来说,程序每次运行至少启动多少个线程?
答:2个,每当Java执行一个类时实际上会启动一个jvm,而一个jvm实际上就是在操作系统中产生一个进程,而main也是1个所以至少2,在Java中所有的线程是同时启动的谁先抢到资源谁先。
2为什么Thread不直接调用run()方法,而是通过start()调用呢。
jdk的Thread里面的start 和run方法是这么定义的
start
public void start()
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
run
public void run()
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
Thread 的子类应该重写该方法。