Java线程类及多线程

进程:

一个操作系统中可以同时运行多个应用程序,每个应用程序被称为一个进程。即系统级别的多线程。

线程:

一个程序同时可能有多个运行场景,每个运行场景就叫做一个线程。

并发:

线程是并发运行的。操作系统将时间划分为若干个时间片,尽可能均匀分给每一个任务,被分配时间片后,任务就有可能被cpu处理,对于单个线程来说,中间间隔时间很短,好像一直在运行,从所有的线程来看,好像一直都在运行。

具体实现:

1)Thread类的实例代表一个并发任务,任何一个线程对象都是Thread类的实例,Thread类是线程的模版,它封装了复杂的线程开启等操作,也兼容不同的操作系统,并发任务的实现只要重写Thread的run方法即可
2)线程调度:线程调度机制会将所有并发任务做统一的调度工作,划分时间片(每次调用可以被cpu执行的时间)给每一个线程。
时间片的大小、被调用的次数大体上会是均匀的,但不能保证绝对均匀。

3)线程的启动与停止:通过调用start()方法,然后run方法也会被自然调用;随着run方法执行结束,线程也就自然结束。
4)线程的创建方式之一:
1.继承Thread。2.重写run方法:run方法中定义定义需要并发执行的任务逻辑代码。

/**
 * 第一步:继承Thread类
 * 第二部:重写run()方法
 * 第三步:创建Thread类的对象,调用start()方法
 * @author 32456
 *
 */
public class Test1 extends Thread{
     @Override
     public void run() {
    	 for(int i = 0;i < 10;i++) {
    		 System.out.println("进程执行了"+i);
    	 }
     }
	public static void main(String[] args) {
		Test1 test = new Test1();
		test.start();
		for(int i = 0;i < 10;i++) {
			System.out.println("主函数执行"+i);
		}
	}
}

5)线程的创建方式二:
将线程与执行逻辑分开,即实现Runnable接口。有了这种接口才有了线程池。

/**
 *  1.实现接口
 *  2.重写run方法
 *  3.创建runnable接口实现
 * @author 32456
 *
 */
public class Test2 implements Runnable{
     @Override
     public void run() {
    	 for(int i = 0;i < 200;i++) {
    		 System.out.println("有人写笔记"+i);
    	 }
     }
     public static void main(String[] args) {
		Test2 test = new Test2();
		Thread thread = new Thread(test);
		thread.start();
		for(int i = 0;i < 2000;i++) {
			System.out.println("做作业"+i);
		}
	}
}

6)Runnable接口:定义了一个类实现Runnable接口,必须重写run方法,在run方法中定义我们要执行的逻辑。
7)线程创建方式三:使用匿名内部类方式创建线程


import java.text.SimpleDateFormat;
import java.util.Date;

public class Test3 implements Runnable{
    @Override

    public void run() {
        System.out.println(Thread.currentThread().getName()+"->启动了");
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"->停止了");
    }

    public static void main(String[] args) throws InterruptedException {
        Test2 test2 = new Test2();
        new Thread(test2,"小明").start();
        new Thread(test2,"老师").start();
        
        while(true) {
        	Date date = new Date(System.currentTimeMillis());
        	Thread.sleep(1000);
        	System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
        }
    }
}

8)线程生命周期:
在这里插入图片描述
9)线程睡眠阻塞:
使当前程序放弃cpu时间,进入阻塞状态。在阻塞状态的线程不会分配时间片。直到该线程结束阻塞状态回到Runnable状态,方可再次获得时间片来让cpu运行。
static void sleep(times)方法:让当前线程主动进入Block阻塞状态,并在time毫秒后回到Runnable状态。
PS:使用Thread.sleep()方法阻塞线程时,强制让我们必须捕获“中断异常”。引发情况:当前线程处于sleep阻塞期间,被另一线程中断阻塞状态时,当前线程会抛出该异常。

10)void interrupt()方法:打断/唤醒线程。一个线程可以提前唤醒另一个sleep Block的线程。
11)线程其它方法:
(1)static void yield():当前线程让出处理器,放弃当前时间片,主动进入Runnable状态等待
(2)final void setPriority(int):设置线程优先级;优先级越高的线程,理论上获取cpu的次数就越多,线程优先级一定要在线程启动前设置!
(3)final void join():等待该线程终止。

12)线程并发安全问题:synchronized关键字,线程安全锁,同步监视器。
多线程在访问同一个数据时(其中有至少一个写操作),可能会引发不安全操作。
(1)哪个线程报错不捕获,则线程死,不影响主程序。
(2)同步:同一时刻只能有一个执行,A和B配合工作,执行有先后顺序。
异步:线程各干各的, 某个线程的执行不会对另一些的执行产生任何影响。
(3)sychronized修饰代码块,限制多线程并发时同时访问该区域。
(4)sychronized修饰方法会对方法上锁,方法就是同步的。
(5)synchronized同步块,可以只对一小部分代码上锁。
(6)线程安全的效率低,如Vector、Hashtable。线程不安全的效率高,如ArrayList、HashMap

13)Daemon后台线程也称为守护线程:当当前进程中所有前台线程死亡后,后台线程将被强制死亡,无论是否还在运行。
(1)守护线程,必须在启动线程前调用
(2)main方法也是靠线程运行的,且是一个前台线程
(3)正在运行的线程都是守护线程时,JVM退出。

14)wait/notify方法
这两个方法定义在Object类中,两个方法的作用是用于协调线程工作的。
(1)等待机制与锁机制密切关联:等待机制与锁机制密切关联:wait/notify方法必须与synchronized同时使用,谁调用wait或notify方法,就锁谁。
(2)wait()方法:当条件将不满足时,则等待。当条件满足时,等待该条件的线程将被唤醒。如:浏览器显示一个图片,displayThread要想显示图片,则必须等待下载线程downloadThread将该图片下载完毕。然后displayThread才可以执行。
(3)notify()方法:随机通知、唤醒一个在当前对象身上等待的线程
(4)notifyAll方法:通知、唤醒所有在当前对象身上等待的线程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值