请关注“知了堂学习社区”,地址:http://www.zhiliaotang.com/portal.php
1.线程和进程
进程:完整的程序功能——暴风影音线程:进程执行单元——播放图像/声音
进程是对线程的一个封装,一个进程至少有一个线程
同时:进程是具有同时性,线程也具有同时性(时间片的抢夺)
本质上就是线程的同时性
进程把线程封装了,进程之间不能资源共享(独立的空间),线程是可以资源共享的
JVM:多线程,执行main函数,GC(垃圾回收,守护线程:平时看不到的线程,会自己工作)
2.多线程-工人模型
每一工人----------线程(Thread)
每一个工人都有任务---Runnable
工人执行任务-----启动多线程
2.1 线程的方式——任务实现runnbale接口,线程就是thread
示例 1:
package thread_1;
public class Thread_1 {
public static void main(String[] args) {
Task task = new Task();//任务
Thread t1 = new Thread(task);//Runnable ---任务
t1.setName("张三");
Thread t2 = new Thread(task);
t2.setName("李四");
t1.start();//启动线程
t2.start();
}
}
class Task implements Runnable{
public void run() {
System.out.println("任务");
}
}
运行结果:
任务
任务
实例二:
class Task implements Runnable{
public void run() {
System.out.println(Thread.currentThread()+"任务");
}
}
Thread.currentThread():当前运行的线程(this)
结果:
Thread[张三,5,main]任务
Thread[李四,5,main]任务
2.2 实现线程——任务就在自己身上,thread实现runnbale接口,直接实现
示例 1:
package thread_1;
public class Thread_2 {
public static void main(String[] args) {
zhangsan zs = new zhangsan();
zs.start();
lisi ls = new lisi();
ls.start();
}
}
class zhangsan extends Thread{
public void run() {
while(true){
System.out.println("我有车");
}
}
}
class lisi extends Thread{
public void run() {
while(true){
System.out.println("我有房");
}
}
}
运行结果:
我有房
我有房
我有房
我有房
我有房
我有房
我有车
我有车
我有车
我有车
我有车
我有车
我有车
实例二:
package thread_1;
public class Thread_2 {
public static void main(String[] args) {
Zhangsan zs = new Zhangsan();
zs.run();
Lisi ls = new Lisi();
ls.run();
}
}
class Zhangsan extends Thread{
public void run() {
while(true){
System.out.println("我有车");
}
}
}
class Lisi extends Thread{
public void run() {
while(true){
System.out.println("我有房");
}
}
}
运行结果:
我有车
我有车
我有车
我有车
我有车
我有车
我有车
我有车
我有车
解释:
直接调用run方法:真正的方法调用,就不是多线程了
方法就是进入方法栈,main就是入口,进栈,直接调用run方法,只有执行完,才执行后面的,但是这里的方法是死循环,所以lisi一直出不来
方法调用,调用的方法只有一条,但是多线程,main方法本身会一直往下执行,每次调到run方法,main方法还是会继续往下执行
2.3 手动中断一个线程 shutup(设置标志位)
示例:
package thread_1;
public class Thread_2 {
public static void main(String[] args) {
Zhangsan zs = new Zhangsan();
zs.start();
zs.shutUp();
Lisi ls = new Lisi();
ls.start();
ls.shutUp();
}
}
class Zhangsan extends Thread{
boolean flag = true;
public void run() {
while(flag){
System.out.println("我有车");
}
}
public void shutUp(){
this.flag = false;
}
}
class Lisi extends Thread{
boolean flag = true;
public void run() {
while(flag){
System.out.println("我有房");
}
}
public void shutUp(){
this.flag = false;
}
}
2.4 总结
1.threa本身实现了Runnable接口,自己设定任务run方法
2.线程的启动调用start方法,而不是run方法,直接调用run方法就是方法的调用
3.中断线程:标志位(flag)
4.Thread.sleep():控制权交出(当前线程休眠)
示例:
package thread_1;
public class Thread_2 {
public static void main(String[] args) {
Zhangsan zs = new Zhangsan();
zs.start();
zs.shutUp();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Lisi ls = new Lisi();
ls.start();
ls.shutUp();
}
}
class Zhangsan extends Thread{
boolean flag = true;
public void run() {
while(flag){
System.out.println("我有车");
}
}
public void shutUp(){
this.flag = false;
}
}
class Lisi extends Thread{
boolean flag = true;
public void run() {
while(flag){
System.out.println("我有房");
}
}
public void shutUp(){
this.flag = false;
}
}
示例 3:
package thread_1;
/**
* 启动一个线程,计算1-1000和
* 主线程打印结果
* @author Administrator
*
*/
public class Thread_3 {
public static void main(String[] args) throws InterruptedException {
Task1 t1 = new Task1();
Thread t = new Thread(t1);
t.start();
Thread.sleep(1000);
System.out.println(t1.getSum());
}
}
class Task1 implements Runnable{
private int sum;
public int getSum() {
return sum;
}
public void run() {
for(int i=1;i<=1000;i++){
this.sum += i;
}
}
}
运行结果:500500
3.线程的状态
新建(new Thread)--------运行(start)----------结束
|
|
阻塞
线程可运行状态:抢到cpu才是真正的运行状态
阻塞:运行过程中,cpu被抢;调用sleep()/wait()方法也是阻塞状态,
结束:标志位
注:在运行状态和阻塞状态是双向的,在运行中,如果cpu被抢,就成为了阻塞状态,在阻塞状态下,也可以抢完cpu,成为运行状态
线程的生命周期(与线程的状态一样):
1.新建状态(new Thread):让一个thread类或其子类的对象被创建但未被执行时,称之为新建状态,这是线程对象已被初始化,并等待着系统的调用
2.运行状态(Runnable):通过start()命令,线程被启动,这是线程处于可运行状态,在线程对列中等待系统分配给其运行时间;一旦线程获得处理器资源,便进入运行状态
3.挂起状态(阻塞):一个正在执行的线程由于某种原因,暂停执行,并让出处理器资源,就会进入挂起状态
注:三种会使线程进入挂起状态:调用sleep();调用wait();被另一个程序阻塞
4.结束(Dead):两种情况:执行完成并退出;线程被提前终止
4.线程的常用的方法
Runable:线程执行其实例类来实现(线程实例类要执行的那些任务)
run方法:线程执行时候的调用(相当于工人模型中方法的本身)
thread的对象就是一个独立的工人,thread实现runnable接口,实现run方法
start方法:线程开始执行,调用该线程的run方法
stop方法:可以终止,但是不推荐使用
interrupt方法:不是中断线程,而是线程受阻(打扰线程的sleep),线程可以马上恢复
sleep():线程休眠,让出cpu,不让出锁
join():等待线程终止
yeild():暂停当前执行的线程对象,并执行其他的线程
setPriority():设置线程的优先级别
isAlive():线程是否为活动状态
wait(): ,会把持有该对象线程的对象控制权交出去,然后处于等待状态。
notify(): 会通知某个正在等待这个对象的控制权的线程可以继续运行。
notyfiAll(): 会通知所有等待这个对象控制权的线程继续运行,如果有多个正在等待该对象控制权时,具体唤醒哪个线程,就由操作系统进行调度。
示例 1:
package thread_1;
/**
* 抛出InterruptException异常
* 线程1 sleep
* 线程2 打扰线程1
* @author Administrator
*
*/
public class Thread_4 {
public static void main(String[] args) {
MyThread t1 = new MyThread();
Mythread2 t2 = new Mythread2(t1);
t1.start();
t2.start();
}
}
class MyThread extends Thread{
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("被打扰了");
e.printStackTrace();
}
}
}
class Mythread2 extends Thread{
private MyThread t1;
public Mythread2(MyThread t1) {
super();
this.t1 = t1;
}
public void run() {
System.out.println("被中断了");
t1.interrupt();
}
}
结果:
被中断了
被打扰了