JAVA笔记 之 Thread线程

线程是一个程序的多个执行路径,执行调度的单位,依托于进程存在。 线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈,是在建立线程时由系统分配的,主要用来保存线程内部所使用的数据,如线程执行函数中所定义的变量。
注意:Java中的多线程是一种抢占机制而不是分时机制。抢占机制指的是有多个线程处于可运行状态,但是只允许一个线程在运行,他们通过竞争的方式抢占CPU。

一、定义一个线程有两种方法:
1、继承java.lang.Thread类,重写run()方法,通过线程的start()方法被JVM自动运行。
public class ThreadTest extend Thread {

@Override
public void run() {
System.out.println("I‘m running!");
};

}

2、实现Runnable接口,实现run方法,作为线程Thread类的参数并通过start()方法调用。
public class ThreadTest implements Runnable {

public void run() {
System.out.println("I‘m running!");
};

}

二、线程的状态
1、新生状态(New):当一个线程的实例被创建即使用new关键字和Thread类或其子类创建一个线程对象后,此时该线程处于新生(new)状态,处于新生状态的线程有自己的内存空间,但该线程并没有运行,此时线程还不是活着的(not alive);
2、就绪状态(Runnable):通过调用线程实例的start()方法来启动线程使线程进入就绪状态(runnable);处于就绪状态的线程已经具备了运行条件,但还没有被分配到CPU即不一定会被立即执行,此时处于线程就绪队列; 此时线程是活着的(alive);
3、运行状态(Running):一旦获取CPU(被JVM选中),线程就进入运行(running)状态,线程的run()方法才开始被执行;在运行状态的线程执行自己的run()方法中的操作,直到调用其他的方法而终止、或者等待某种资源而阻塞、或者完成任务而死亡;如果在给定的时间片内没有执行结束,就会被系统给换下来回到线程的等待状态;此时线程是活着的(alive);
4、阻塞状态(Blocked):通过调用join()、sleep()、wait()或者资源被暂用使线程处于阻塞(blocked)状态;处于Blocking状态的线程仍然是活着的(alive)
5、死亡状态(Dead): 执行run()方法完毕或者异常退出后的状态。对于一个处于Dead状态的线程调用start()方法,会出现一个运行期(runtime exception)的异常;处于Dead状态的线程不是活着的(not alive)。

三、线程的常用属性
1、优先级(priority)
2、thread.sleep()/sleep(long millis)
3、Thread.yield()
4、thread.join()
5、object.wait()
6、object.notify()/notifyAll()
7、synchronized block

四、Thread synchronized
1、非static的synchronized方法
被锁定的是类的对象,在多线程中,这个对象不能被多个线程同时访问,但是所属类的其他对象的此方法不受限制;
如果一个对象有多个非static的同步方法,一旦进入其中一个,就锁定此对象,无法进入其他同步方法
2、static的synchronized方法
由于static的成员不属于类对象,而是属于Class,因此,这里锁定的是Class类,而不是对象,所以如果static和非static的同步方法共存,
没有冲突。但是如果两个static同步方法,无论是否是不同对象,都是互斥的,因为他们都属于同一个Class类。
3、synchronized同步块
synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块之外的其他代码是可以被多个线程同时访问到的。
注意:被synchronized保护的数据应该是私有的。

五、Lock锁
Lock的锁定是通过代码实现的,而 synchronized 是在 JVM 层面上实现的。
synchronized在锁定时如果方法块抛出异常,JVM 会自动将锁释放掉,不会因为出了异常没有释放锁造成线程死锁。但是 Lock 的话就享受不到 JVM 带来自动的功能,出现异常时必须在 finally 将锁释放掉,否则将会引起死锁。
在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。

ReentrantLock
ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。
Atomic
和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。

时间: 2024-08-29 15:19:05

JAVA笔记 之 Thread线程的相关文章

11.6-全栈Java笔记:什么是线程同步

 同步问题的提出 现实生活中,我们会遇到"同一个资源,多个人都想使用". 比如:教室里,只有一台电脑,多个人都想使用.天然的解决办法就是,在电脑旁边,大家排队.前人使用完后,后人再使用. 线程同步的概念 处理多线程问题时,多个线程同时访问同一个对象,并且一个线程还想修改这个对象. 这时候,我们就需要用到"线程同步". 线程同步其实就是一种等待机制,多个线程需要同时访问同一个对象,则线程进入这个对象的等待池(wait pool)形成队列,等待前面的线程使用完毕后,下一

11.7-全栈Java笔记:如何实现线程同步

由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问时的冲突问题. 由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized 方法和 synchronized 块:  synchronized方法 通过在方法声明中加入 synchronized

JAVA笔记13__创建线程/线程休眠/等待线程终止/线程中断/守护线程

/** * 线程:是进程的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少有一个进程(单线程程序) * 多线程两种实现方法:1.继承Thread类 2.实现Runnable接口 */ public class Main { public static void main(String[] args) { MyThread t1 = new MyThread(); t1.start(); //启动线程 System.out.println("main"); S

【Java基础学习笔记】Thread+JLabel实现线程

package Thread_Test; import java.awt.Container; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.SwingConstants; public class Thread_Swing extends JFrame { /** * */ private static final long serialVersionUID = 1L; private JLab

java笔记--使用线程池优化多线程编程

使用线程池优化多线程编程 认识线程池 在Java中,所有的对象都是需要通过new操作符来创建的,如果创建大量短生命周期的对象,将会使得整个程序的性能非常的低下.这种时候就需要用到了池的技术,比如数据库连接池,线程池等. 在java1.5之后,java自带了线程池,在util包下新增了concurrent包,这个包主要作用就是介绍java线程和线程池如何使用的. 在包java.util.concurrent下的 Executors类中定义了Executor.ExecutorService.Sche

java笔记--关于Object类与线程相关的方法

关于Object类中的线程方法 Object类是所有Java类的 父类,在该类中定义了三个与线程操作有关的方法,使得所有的Java类在创建之后就支持多线程 这三个方法是:notify(),notifyAll(),wait(),这几个方法都是用来控制线程的运行状态的. 方法列表如下: notify() : 唤醒在此对象监视器上等待的单个线程 notifyAll() : 唤醒在此对象监视器上等待的所有线程 wait() : 在其他线程时调用此对象的notify()或者notifyAll()方法前,导

java笔记--用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程

用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程 ThreadLocal在我的笔记"关于线程同步"的第5种方式里面有介绍,这里就不多说了. --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3899890.html  "谢谢-- Callable<V>接口类似于Runnable,两者都是为了哪些其实例可能被另一个线程执行的类设计的, 但是Runnable不会返回

java笔记--关于线程通信

关于线程通信 使用多线程编程的一个重要原因就是线程间通信的代价比较小 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3897773.html "谢谢-- 关键技术: yield(): Thread类的一个静态方法,用来暂停当前正在执行的线程对象,并执行其他线程 public static void yield(){} 代码实例: 实现线程间的发送和接收消息 package com.xhj.thread; /** * 线程之间的通信

java笔记--使用事件分配线程更新Swing控件

使用事件分配线程更新Swing控件: Swing并不是线程安全的,如果在多个线程中更新Swing控件,则很可能造成程序崩溃. 为了避免这种问题,可以使用时间分配线程来更新Swing控件. EventQueue 是一个与平台无关的类,它将来自于底层同位体类和受信任的应用程序类的事件列入队列. 它封装了异步事件指派机制,该机制从队列中提取事件,然后通过对EventQueue调用dispatchEvent(AWTEvent) 方法来指派这些事件(事件作为参数被指派).该机制的特殊行为是与实现有关的.为