创建线程和线程的常用方法(一)

创建线程和线程的常用方法

今天学习了线程的相关知识,通过查找资料和观看视频学习总结了一下创建线程的过程和线程的一些常用方法。

一:进程和线程的关系

1. 进程

进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。

2. 线程

线程是一条执行路径,是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。

一个正在运行的软件就是一个进程,一个进程可以同时运行多个任务, 可以简单的认为进程是线程的集合。

线程是一条可以执行的路径。多线程就是同时有多条执行路径在同时(并行)执行。

3. 进程与线程的关系

一个程序就是一个进程,而一个程序中的多个任务则被称为线程。进程是表示资源分配的基本单位,又是调度运行的基本单位。,亦即执行处理机调度的基本单位。 进程和线程的关系:

一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程是操作系统可识别的最小执行和调度单位。

资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量,即每个线程都有自己的堆栈和局部变量。

处理机分给线程,即真正在处理机上运行的是线程。

线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。

4.多线程

多线程可以提高程序执行的效率,多线程的特点是一般线程之间比较独立,互不影响,一个线程发生问题,一般不影响其它线程。

二:线程的创建

常见的线程创建方法:

1.继承Thread类,重写run方法

public class Main { 
    //继承了Thread类
    public static void main(String[] args) {
         new MyThread().start();
    }
}
class MyThread extends Thread {
	//重写run方法
    @Override
    public void run() {
		System.out.println(Thread.currentThread().getName()+":你好");
		}
}

2.实现runnable接口,重写run()方法,然后用Thread类来包装

public class Main {
    public static void main(String[] args) {
    	 // 将Runnable实现类作为Thread的构造参数传递到Thread类中,然后启动Thread类
        MyRunnable runnable = new MyRunnable();
        new Thread(runnable).start();
    }
}

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "你好!"
    }
}

这两种方式最终都是调用Thread类的start()方法来启动线程的,两种方式都是围绕着Thread和Runnable,继承Thread类把run()写到类中,实现Runnable接口是把run()方法写到接口中然后再用Thread类来包装。
两种方式的比较:
Thread: 继承方式, 不建议使用, 因为Java是单继承的,继承了Thread就没办法继承其它类了,不够灵活。
Runnable: 实现接口,比Thread类更加灵活,没有单继承的限制。

三:线程中常用的方法

1. start() 与 run()

start(): 启动一个线程,线程之间是没有顺序的,是按CPU分配的时间片来回切换的。

run(): 调用线程的run方法,就是普通的方法调用,具体要启动一个线程来运行线程体中的代码(run()方法)还是通过start()方法来实现,调用run()方法就是一种顺序编程不是并发编程。

2. sleep() 与 interrupt()

sleep(long millis): 睡眠指定时间,程序暂停运行,睡眠期间会让出CPU的执行权,去执行其它线程,同时CPU也会监视睡眠的时间,一旦睡眠时间到就会立刻执行(因为睡眠过程中仍然保留着锁,有锁只要睡眠时间到就能立刻执行)。

sleep(): 睡眠指定时间,即让程序暂停指定时间运行,时间到了会继续执行代码,如果时间未到就要醒需要使用interrupt()来随时唤醒。
interrupt(): 唤醒正在睡眠的程序,调用interrupt()方法,会使得sleep()方法抛出InterruptedException异常,当sleep()方法抛出异常就中断了sleep的方法,从而让程序继续运行下去。

3. wait() 与 notify()

wait(): 导致线程进入等待阻塞状态,会一直等待直到它被其他线程通过notify()或者notifyAll唤醒。该方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。

wait(long timeout): 时间到了自动执行,类似于sleep(long millis)。

notify(): 该方法只能在同步方法或同步块内部调用, 随机选择一个(注意:只会通知一个)在该对象上调用wait方法的线程,解除其阻塞状态。

notifyAll(): 唤醒所有的wait对象。

注意:

Object.wait()和Object.notify()和Object.notifyall()必须写在synchronized方法内部或者synchronized块内部
调用wait和notify必须使用同一个对象来调用。
让哪个对象等待wait就去通知notify哪个对象,不要让A对象等待,结果却去通知B对象,要操作同一个对象。

4. sleep() 与 wait()的区别

sleep在Thread类中,wait在Object类中。

sleep()方法睡眠时不会释放锁,而wait()方法会释放锁。

sleep使用interrupt()来唤醒,wait需要notify或者notifyAll来通知。

5. yield()

交出CPU的执行时间,不会释放锁,让线程进入就绪状态,等待重新获取CPU执行时间。 和sleep不同的是当再次获取到CPU的执行,不能确定是什么时候,而sleep是能确定什么时候再次执行。两者的区别就是sleep后再次执行的时间能确定,而yeid是不能确定的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值