java线程基础
来源:互联网 发布:python灰帽子讲的什么 编辑:程序博客网 时间:2024/05/16 05:15
一、什么是线程
线程在某些场合可以当做轻量级进程来理解,是程序执行的最小单位(是系统调度和分派的基本单位),线程本身是由唯一id、当前指令针、寄存器集合、堆栈组成。线程是进程中的一个实体,线程本身除运行资源外,不拥有其他系统资源,但是可以与同一个进程组的其他线程共享资源,线程之间是相互制约的,呈现出间断性。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
二、线程的状态
线程分为5个状态
1、新建:例如:new Thread();这个时候只是新创建了一个线程,线程本身还没有任何代码。
2、就绪:创建线程后 执行了start()方法,会进行线程运行时需要的资源创建,资源创建完成后调用run()方法(这里只是调用 了 run,并没有真正开始执行),当start()正确返回后,线程进入就绪状态。
注:调用了start()方法并不意味着线程会马上执行,可能会由于cup时间片的竞争,或者当前线程需要其他线程占用的资源释放后才能运行,这些情况的出现会延迟当前线程的开始执行时间
3、运行:cup时间片和运行资源被当前线程抢到后 开始执行run()方法,只有开始执行run方法了线程才是运行状态
4、阻塞:简单的来说就是线程由于某种原因暂时停止了继续运行。阻塞只是让出了cpu的时间片,并不是结束掉线程。
一般有以下情况会导致阻塞:(1)、调用了sleep()方法进行了睡眠。(2)在某个I/O操作上等待,比如网络Socket中服务器监听,或者键盘等待输入,或者等待资源释放等等情况。(3)线程想要得到一个锁,但是资源被其他线程占用,必须等待被占用线程释放资源。(4)线程等待条件触发执行
5、死亡:线程运行完成后自然进入死亡状态,表示线程终结了,如果run()方法中有未捕获的异常产生,会导致线程意外停止。死亡的线程是不能调用start()方法的,会抛出java.lang.IllegalThreadStateException异常
三、如何创建一个线程
1、继承Thread类,实现 public void run(){}方法,这种方法的坏处是一旦A类继承了Thread类,就不可以再被其他类继承A的线程特性,线程方法必须是在A类中直接实现
2、实现Runnable接口,需要实现run()方法,这种方式可以再去继承其他对象。
3、实现Callable接口
步骤:
(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
一般线程如果没有重复执行的可能性,那么走完run方法会自然结束掉,也有些其他场景是无限循环的,有3种方式结束线程:
1、使用退出标志控制,在线程外部声明一个布尔对象,线程内部用布尔值来控制线程
代码====================
public volatile boolean exit = false; //使用volatile 修饰,保证当前对象同时只能有一个对象在修改
public void run()
{
while (!exit);
}
public static void main(String[] args) throws Exception
{
ThreadFlag thread = new ThreadFlag();
thread.start();
sleep(5000); // 主线程延迟5秒
thread.exit = true; // 终止线程thread
thread.join();
System.out.println("线程退出!");
}
2、使用stop方法,这种相当于立即强制性结束掉一个线程,会导致处理信息丢失等待问题,不到万不得已,还是不要用这种方式。
1、继承Thread类,实现 public void run(){}方法,这种方法的坏处是一旦A类继承了Thread类,就不可以再被其他类继承A的线程特性,线程方法必须是在A类中直接实现
2、实现Runnable接口,需要实现run()方法,这种方式可以再去继承其他对象。
3、实现Callable接口
步骤:
(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并启动新线程
代码 ====================
四、如何结束一个线程代码 ====================
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class Ts implements Callable{
@Override
public Object call() throws Exception {
// TODO Auto-generated method stub
return null;
}
public static void main(String[] args) {
Ts t=new Ts();//由Callable创建一个FutureTask对象
// FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了 Future和Runnable接口
FutureTask task = new FutureTask(t);
Thread thread = new Thread(task);
thread.start();
}
} 一般线程如果没有重复执行的可能性,那么走完run方法会自然结束掉,也有些其他场景是无限循环的,有3种方式结束线程:
1、使用退出标志控制,在线程外部声明一个布尔对象,线程内部用布尔值来控制线程
代码====================
public volatile boolean exit = false; //使用volatile 修饰,保证当前对象同时只能有一个对象在修改
public void run()
{
while (!exit);
}
public static void main(String[] args) throws Exception
{
ThreadFlag thread = new ThreadFlag();
thread.start();
sleep(5000); // 主线程延迟5秒
thread.exit = true; // 终止线程thread
thread.join();
System.out.println("线程退出!");
}
2、使用stop方法,这种相当于立即强制性结束掉一个线程,会导致处理信息丢失等待问题,不到万不得已,还是不要用这种方式。
3、使用interrupt方法
(1)、在线程处于阻塞状态时使用interrupt(),如果阻塞原因是调用了 sleep(),那么会抛出异常InterruptedException
代码======================
public class ThreadInterrupt extends Thread
{
public void run()
{
try
{
sleep(50000); // 延迟50秒
}
catch (InterruptedException e)
{
System.out.println(e.getMessage());
}
}
public static void main(String[] args) throws Exception
{
Thread thread = new ThreadInterrupt();
thread.start();
System.out.println("在50秒之内按任意键中断线程!");
System.in.read();
thread.interrupt();
thread.join();
System.out.println("线程已经退出!");
}
}
(2)、使用while(!isInterrupted()){}来判断线程是否被中断,如果返回false,就调用interrupt()方法,这样的结果是,线程会找个机会自己退出来
代码================================
(1)、在线程处于阻塞状态时使用interrupt(),如果阻塞原因是调用了 sleep(),那么会抛出异常InterruptedException
代码======================
public class ThreadInterrupt extends Thread
{
public void run()
{
try
{
sleep(50000); // 延迟50秒
}
catch (InterruptedException e)
{
System.out.println(e.getMessage());
}
}
public static void main(String[] args) throws Exception
{
Thread thread = new ThreadInterrupt();
thread.start();
System.out.println("在50秒之内按任意键中断线程!");
System.in.read();
thread.interrupt();
thread.join();
System.out.println("线程已经退出!");
}
}
(2)、使用while(!isInterrupted()){}来判断线程是否被中断,如果返回false,就调用interrupt()方法,这样的结果是,线程会找个机会自己退出来
代码================================
public class ThreadA extends Thread {
private boolean isInterrupted=false;
int count=0;
public void interrupt(){
isInterrupted = true;
super.interrupt();
}
public void run(){
System.out.println(getName()+"将要运行...");
while(!isInterrupted){
System.out.println(getName()+"运行中"+count++);
try{
Thread.sleep(400);
}catch(InterruptedException e){
System.out.println(getName()+"从阻塞中退出...");
System.out.println("this.isInterrupted()="+this.isInterrupted());
}
}
System.out.println(getName()+"已经终止!");
}
}
======关于线程中断interupt()中断线程
一个线程从运行到真正的结束,应该有三个阶段:正常运行.、处理结束前的工作,也就是准备结束.、结束退出.。
如何能确保线程真正停止?在线程同步的时候有一个叫“二次惰性检测”(double check),能在提高效率的基础上又确保线程真正中同步控制中。那么我把线程正确退出的方法称为“双重安全退出”,就是不以isInterrupted ()为循环条件
五、线程常用的方法
1、 sleep()这是一个静态方法,只能控制当前正在运行的线程,sleep能保证线程最短不会运行时间,但是不能有效保证多少时间后能继续运行,这与当前cup时间片与系统资源调度有关。
2、getState()得到该线程的状态
3、isAlive()确定当前线程是否处在活动状态。可运行或阻塞返回true,其他状态返回false
4、isInterrupted()判断线程是否被中断,已经中断返回true,否则为false
5、interrupt()中断线程。一个线程强制停止是很危险的,这个方法并不会强制停止线程,而是告诉这个线程自己可以找个地方停下来了。如果无法中断(例如进入一个同步锁代码块时,是不能被中断的),会抛出SecurityException,但是 ReentrantLock 支持可中断的获取模式即 tryLock(long time, TimeUnit unit)。
6、getPriority()返回线程的优先级
7、setPriority()更改线程的优先级
8、join()等待线程终止,有参数可以设置等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。
9、yield ()暂停当前正在执行的线程,并执行其他线程
六、wait()与sleep()的区别
sleep()可以将一个线程睡眠,参数可以指定一个时间。
wait()可以将一个线程挂起,直到超时或者该线程被唤醒。(java.lang.Object类中提供了wait(), notify()和notifyAll()方法来操作线程)
9、yield ()暂停当前正在执行的线程,并执行其他线程
六、wait()与sleep()的区别
sleep()可以将一个线程睡眠,参数可以指定一个时间。
wait()可以将一个线程挂起,直到超时或者该线程被唤醒。(java.lang.Object类中提供了wait(), notify()和notifyAll()方法来操作线程)
1、功能差不多,都用来进行线程控制,他们最大本质的区别是:sleep()不释放同步锁,wait()释放同步锁
2、用法的上的不同是:sleep(milliseconds)可以用时间指定来使他自动醒过来,如果时间不到你只能调用interreput()来强行打断;
wait()可以用notify()直接唤起.
sleep是Thread类的静态方法。sleep的作用是让线程休眠制定的时间,在时间到达时恢复,也就是说sleep将在接到时间到达事件事恢复线程执行,例如:
try{
System.out.println("I'm going to bed");
Thread.sleep(1000);
System.out.println("I wake up");
}
catch(IntrruptedException e) {
}
wait是Object的方法,也就是说可以对任意一个对象调用wait方法,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者,例如:
try{
obj.wait();
}
catch(InterrputedException e) {
}
3、这两者的施加者是有本质区别的
sleep()是让某个线程暂停运行一段时间,其控制范围是由当前线程决定,也就是说,在线程里面决定。
wait()是由某个确定的对象来调用的,将这个对象理解成一个传话的人,当这个人在某个线程里面说"暂停!",也是obj.wait(),这里的暂停是阻塞 ,再等一个传话人说“ok继续执行”,就继续起来执行
两者都可以让线程暂停一段时间,但是本质的区别是一个线程的运行状态控制,一个是线程之间的通讯的问题
总结sleep和wait的区别有:
1,这两个方法来自不同的类分别是Thread和Object
2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3,wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在
任何地方使用
synchronized(x){
x.notify()
//或者wait()
}
4,sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
2、用法的上的不同是:sleep(milliseconds)可以用时间指定来使他自动醒过来,如果时间不到你只能调用interreput()来强行打断;
wait()可以用notify()直接唤起.
sleep是Thread类的静态方法。sleep的作用是让线程休眠制定的时间,在时间到达时恢复,也就是说sleep将在接到时间到达事件事恢复线程执行,例如:
try{
System.out.println("I'm going to bed");
Thread.sleep(1000);
System.out.println("I wake up");
}
catch(IntrruptedException e) {
}
wait是Object的方法,也就是说可以对任意一个对象调用wait方法,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者,例如:
try{
obj.wait();
}
catch(InterrputedException e) {
}
3、这两者的施加者是有本质区别的
sleep()是让某个线程暂停运行一段时间,其控制范围是由当前线程决定,也就是说,在线程里面决定。
wait()是由某个确定的对象来调用的,将这个对象理解成一个传话的人,当这个人在某个线程里面说"暂停!",也是obj.wait(),这里的暂停是阻塞 ,再等一个传话人说“ok继续执行”,就继续起来执行
两者都可以让线程暂停一段时间,但是本质的区别是一个线程的运行状态控制,一个是线程之间的通讯的问题
总结sleep和wait的区别有:
1,这两个方法来自不同的类分别是Thread和Object
2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3,wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在
任何地方使用
synchronized(x){
x.notify()
//或者wait()
}
4,sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
0 0
- 线程之一:JAVA线程基础
- 线程之一:JAVA线程基础
- java线程学习基础
- Java基础 -- 线程
- Java基础 -- 线程2
- JAVA线程基础
- Java 线程基础
- Java线程基础1
- java线程基础
- java基础 线程
- Java 线程基础
- java 线程基础
- 十三、Java线程基础
- java线程基础
- java基础之线程
- JAVA线程基础(一)
- Java基础之线程
- java基础--线程总结
- ARM指令集
- $.extend
- 洛谷在线测试P3378_模板堆
- SpringMVC整合Shiro
- Java读写Excel之POI超入门
- java线程基础
- Kotlin Primer·第四章·Kotlin 的类特性(下)
- 苹果【DP】
- HTML学习笔记
- 第一篇文章
- Linux 常用命令 day2
- k2利用花生壳搭建ss教程
- Java总结篇系列:Java多线程(三)
- EditBox 控件的用法