java线程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java线程相关的知识,希望对你有一定的参考价值。
1、进程(Process),线程(Thread)区别
进程:每个独立执行的程序称为进程。
线程:线程是一个程序内部的一条执行路径。
- 进程:进程是一个静态的概念
- 线程:一个进程里面有一个主线程叫main()方法,是一个程序里面的,一个进程里面不同的执行路径。
- 在同一个时间点上,一个CPU只能支持一个线程在执行。因为CPU运行的速度很快,因此我们看起来的感觉就像是多线程一样。
2、创建新线程两种方法:
(1)继承Thread类 重写run()方法
启动方法:TikectThread tikectThread = new TikectThread(),
tikectThread.start()
(2)定义"Runnable"接口的实现类
与实现Thread类的线程启动方法不同:
(1)首先创建此线程类的实例:TikectThread tikectThread = new TikectThread()
(2)把线程类实例作为参数传递给线程实例:Thread thread1 = new Thread(tikectThread)
(3)启动:线程再启动的时候是调用 start()方法,而不是run()方法
4、线程的五个状态:
(1)创建
(2)就绪
(3)运行
(4)阻塞
(5)终止
5、线程的方法:
(1)public void start()启动线程
(2)public static Thread currentThread()// Thread currentThread()返回当前正在执行的线程的引用对象
(3)public ClassLoader getContextClassLoader()// getContextClassLoader()返回该线程的上下文 ClassLoader
(4)public final boolean isAlive()// isAlive测试线程是否处于激活状态
(5)Thread.state getState()// 返回线程状态
(6)public final String getName()// 返回线程名称
(7)public final void setName(String name)// 设置线程名称
(8)public final void setDaemon(boolean on)// 将该线程标记为守护线程或用户线程
6、线程调度:
线程睡眠
(1)public static void yield()暂停当前正在执行的线程对象,并执行其他线程
线程让步
(2)public static void sleep(long millis) throws InterruptedException
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权
线程加入
(3)join() throws InterruptedException 方法 在当前线程中调用另一个线程的 join()方法,则当前线程转入WAITING状态,直到另一个线程运行结束,当前线程再由阻塞转为就绪状态
下边的线程等待、唤醒方法只能在被同步化(synchronized)的方法或代码块中调用
线程等待
(4)Object 类中的wait() throws InterruptedException 方法,导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 唤醒方法。
线程唤醒
(5) Object 类中的notify()方法,唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的。 Object类中的notifyAll()方法,唤醒在此对象监视器上等待的所有线程
几个示例:
线程礼让
1 public class TestThreadYield { 2 public static void main(String[] args) { 3 System.out.println("主线程:" + Thread.currentThread().getName()); 4 Thread thread1 = new Thread(new MyThread2()); 5 thread1.start(); 6 Thread thread2 = new Thread(new MyThread2()); 7 thread2.start(); 8 } 9 } 10 class MyThread2 implements Runnable{ 11 public void run() { 12 for(int i = 0; i < 100; i++){ 13 System.out.println(Thread.currentThread().getName()+ ":" + i); 14 if(i % 10 == 0){ Thread.yield(); //线程让步 } 15 } 16 } 17 }
线程合并
1 public class TestThreadJoin { 2 public static void main(String[] args) { 3 Thread thread1 = new Thread(new MyThread3()); 4 thread1.start(); 5 for (int i = 1; i <= 100; i++) { 6 System.out.println(Thread.currentThread().getName() + ":" + i); 7 if (i == 50) { 8 try { thread1.join(); //线程合并 9 } catch (InterruptedException e) { e.printStackTrace(); } 10 } 11 } 12 } 13 } 14 class MyThread3 implements Runnable{ 15 public void run() { 16 for (int i = 1; i <= 50; i++) { 17 System.out.println(Thread.currentThread().getName() + ":" + i); 18 try { Thread.sleep(100); 19 } catch (InterruptedException e) { e.printStackTrace(); } 20 } 21 } 22 }
7、线程优先级:setPriority()、getPriority()
Thread 类有以下三个静态常量:
.static int MIN_PRIORITY 线程可以具有的最低优先级,取值为 1
.static int NORM_PRIORITY 分配给线程的默认优先级,取值为 5
.static int MAX_PRIORITY 线程可以具有的最高优先级,取值为 10
8、多线程安全问题
当run()方法体内的代码操作到了成员变量(共享数据)时,就可能会出现多线程安全问题(线程不同步问题)
编程技巧:
在方法中尽量少操作成员变量,多使用局部变量
9、线程的同步:
(1)在Java语言中,引入对象互斥锁的概念,保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记保证在任一时刻,只能有一个线程访问对象
(2)关键字synchronized用来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。
(3)一个方法使用关键字synchronized修饰后,当一个线程A使用这个方法时,其他线程想使用这个方法就必须等待,直到线程A使用完该方法
synchronized放在对象前面限制一段代码的执行
synchronized(this){需要同步的代码;}
synchronized放在方法声明中,表示整个方法为同步方法:
public synchronized void sale()
10、线程死锁
死锁的原因:线程1锁住资源A等待资源B,线程2锁住资源B等待资源A,两个线程都在等待自己需要的资源,而这些资源被另外的线程锁住,这些线程你等我,我等你,谁也不愿意让出资源,这样死锁就产生了
解决死锁的办法:加大锁的粒度
11、理解线程的等待和唤醒
12、多线程编程的一般规则
(1)如果两个或两个以上的线程都修改一个对象,那么把执行修改的方法定义为被同步的,如果对象更新影响到只读方法,那么只读方法也要定义成同步的.
(2)不要滥用同步。如果在一个对象内的不同的方法访问的不是同一个数据,就不要将方法设置为synchronized的.
(3)如果一个线程必须等待一个对象状态发生变化,那么他应该在对象内部等待,而不是在外部。他可以通过调用一个被同步的方法,并让这个方法调用wait().
(4)每当一个方法返回某个对象的锁时,它应当调用notifyAll()来让等待队列中的其他线程有机会执行.
(5)记住wait()和notify()/notifyAll()是Object类方法,而不是Thread类的方法。仔细查看每次调用wait()方法,都有相应的notify()/notifyAll()方法,且它们均作用于同一个对象.
以上是关于java线程的主要内容,如果未能解决你的问题,请参考以下文章