线程的知识点

线程

一、进程与线程
进程就是正在运行的程序。线程是程序执行单元,执行路径,是程序使用cpu的最基本单位。其关系为
进程包含线程,进程是有若干线程组成。
1.多进程与多线程
多进程:就是可以在同一时间断内执行多个任务,也就是计算机即可以运行qq的同时,运行酷狗。
多线程:程序有多条执行路径,即执行qq聊天窗口,也可以打开新的窗口。
(1)多线程的意义
多线程是为了提高程序的使用效率,程序的执行就是抢占cpu的资源,cpu的执行权。多个进程是抢占这个资源,而其中 的某个一个继承如果执行路径比较多,就会有更高的几率抢占到CPU的执行权

二、线程
1、进程的创建
线程依赖于进程,所以必须创建进程,进程是系统已经创建好的。Java是不能直接调用系统功能的,
Java可以调用C/C++写好的程序来实现多线程的程序。
(1)线程的创建方式1
1.自定义一个类去继承于Thread
2.在自定义类重写run()方法
run()才是线程运行的核心方法
不是类中的所有代码都需要被线程所执行。
而这个时候,为了区分哪些代码能被线程所执行,java提供了Thread类中的run()用来包含那些线程执行的代码
3.创建对象
4.启动线程
例1:

package com.ThreadDemo1;

public class ThreadClass extends Thread{			//定义一个类继承Thread
private String name;
public ThreadClass() {	
}

public ThreadClass(String name) {
	
	this.name = name;
}
@Override
public void run() {									//重写run方法
	// TODO Auto-generated method stub
	for (int i = 0; i < 30; i++) {
		System.out.println(name+i);	//此处的名字可以用Thread.currentThread():返回对当前正在执行的线程对象,也可以
		//	用getName()
	}
}

}

package com.ThreadDemo1;

public class ThreadDemo {
public static void main(String[] args) {
	// TODO Auto-generated method stub
	ThreadClass t=new ThreadClass("二狗");	//创建线程对象
	t.start();	//线程执行
	ThreadClass t1=new ThreadClass("狗蛋");
	t1.start();
}

}

2、线程的优先级

(1)如何获取线程对象的优先级呢?

	public final int getPriority():返回线程对象的优先级

如何设置线程对象的优先级呢?

	public final void setPriority(int newPriority):更改此线程的优先级。 

注意:线程的默认优先级:5
线程优先级的范围是:1-10
线程优先级高仅仅表示线程获取CPU时间片的几率高,但是要在次数比较多,或者多运行的时候才能看到比较效果

3、线程睡眠

线程失眠就是线程的暂停,也就是线程停止一段时间,然后再继续执行

例2:
		
package com.ThreadDemo2;

import java.util.Date;

public class ThreadSleep extends Thread{
@Override
public void run() {
	// TODO Auto-generated method stub
	for (int i = 0; i < 30; i++) {
		System.out.println(Thread.currentThread().getName()+i+new Date());
		try {
			Thread.sleep(2000);		//线程等待两秒再继续执行
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
}

package com.ThreadDemo2;

public class ThreadDemo {

public static void main(String[] args) {
	// TODO Auto-generated method stub
	ThreadSleep sleep=new ThreadSleep();
	sleep.setName("刘亦菲");
	sleep.start();
}

}

5、线程加入

public final void join():等待这个线程死亡。 也就是说等待一个进程死亡之后,另外的进程才会执行

6、线程礼让

public static void yield():暂停当前正在执行的线程对象,并执行其他的线程。
让多个线程的执行更加和谐,但是不能保证一人一次,礼让应当写在run()里

扫描二维码关注公众号,回复: 3545971 查看本文章

7、后台线程

public final void setDaemon(boolean on):将此线程标记为 后台线程或用户线程。
当正在运行的线程都是守护线程,JVM退出。该方法必须在启动线程前调用,
守护线程,就是当主线程死了,子线程也活不了多久。

8、中断线程

public final void stop():让线程停止,过时了。但是还是可以用的。
public void interrupt():中断线程,把线程的状态终止,并抛出一个InterruptException.
例3:

package com.hwua.ThreadDemo2;
import java.util.Date;
public class ThreadStop extends Thread{
@Override
public void run() {
	while(true){
	System.out.println("开始执行:"+new Date());
	
	//我要休息10秒钟,请不要打扰我
	try {
		Thread.sleep(1000*5);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block

		System.out.println("线程已经被停止了");
		break;
		}
	}
	System.out.println("结束执行:"+ new Date());
}

}

package com.hwua.ThreadDemo2;
/*
 * 线程的休眠:线程的暂停
 * */
	
	public class ThreadSleepDemo {
	
	public static void main(String[] args) throws InterruptedException {
	// TODO Auto-generated method stub
	
	Thread currentThread = Thread.currentThread();
	
	ThreadSleep sleep = new ThreadSleep();
	sleep.setName("刘亦菲");
	
	sleep.start();
	
	sleep.stop();
}

}

三、线程的创建方式2

(1)实现线程方式2:实现Runnable接口
步骤:

	A.自定义类MyRunnable实现Runnable接口
	B.重写run()方法
	C.创建MyRunnable类的对象
	D.创建Thread类的对象,并把步骤C的对象作为构造参数传递

例4:

package com.ThreadDemo4;

public class RunableDemo implements Runnable{		//自定义类实现Runnable接口

@Override
public void run() {					//重写run()方法
	// TODO Auto-generated method stub
	for (int i = 0; i < 100; i++) {
		System.out.println(Thread.currentThread().getName()+i);		//只能用Thread.currentThread()获得对象
	}
}

}

package com.ThreadDemo4;

public class MyRunnble {

public static void main(String[] args) {
	// TODO Auto-generated method stub
		RunableDemo rd=new RunableDemo();		//创建对象
		Thread t1=new Thread(rd,"杨过");		//把对象作为构造参数传入
		t1.start();
}

}
练习
某电影院目前正在上映经典大片,共有100张票,而它有3个售票窗口,请设计一个程序模拟该电影院售票系统

例5

package com.hwua.ThreadDemo4;

public class SellTicket extends Thread{

private static int tickes=100;
//因为static所修饰的变量 只会初始化一次。

@Override
public void run() {		//重写run()方法
	// TODO Auto-generated method stub
	while(true){
		if(tickes>0){		//票还有剩余就可以购买
			System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickes--)+"张票");	//
		}else{
			break;
		}
	}
}

}

package com.hwua.ThreadDemo4;
public class SellTicketDemo {

public static void main(String[] args) {
	// TODO Auto-generated method stub
	SellTicket st1 = new SellTicket();
	st1.setName("窗口1");
	SellTicket st2 = new SellTicket();
	st2.setName("窗口2");
	SellTicket st3 = new SellTicket();
	st3.setName("窗口3");
	
	
	st1.start();
	st2.start();
	st3.start();	
}

}

(2)、synchronized

同步代码是用于解决线程的安全问题,在有数据共享的时候,常会出现线程安全问题,这个时候就
需要同步代码块或者是 同步方法去实现线程的安全
1、会出现线程安全问题的条件
A 是否是多线程环境
B 是否有共享数据
C 是否有多条语句操作共享数据

为了解决线程安全的问题,引入了安全机制
第一种方法:同步代码块:
synchronized(对象){
//需要同步的代码
}
对象是随便创建一个对象
同步的代码是把多条语句操作共享数据的代码的部分包起来
需要注意的是:同步可以解决线程安全问题的根本原因就在那个对象上,该对象如同锁的功能。
多个线程必须是同一把锁。
例6:

package com.hwua.ThreadDemo5;

public class SellTicket implements Runnable{

private  int tickes=1000;
private Object obj = new Object();
@Override
public  void run() {
	// TODO Auto-generated method stub
	while(true){
		synchronized(this){		//同步代码块
		if(tickes>0){
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickes--)+"张票");
		}else{
			break;
		}
	}
	}
}

}

package com.hwua.ThreadDemo5;

import com.hwua.ThreadDemo4.SellTicket3;
public class SellTicketDemo {

public static void main(String[] args) {
	// TODO Auto-generated method stub
	 SellTicket ss = new SellTicket();
		Thread t1 = new Thread(ss, "窗口1");
		Thread t2 = new Thread(ss, "窗口2");
		Thread t3 = new Thread(ss, "窗口3");
		t1.start();
		t2.start();
		t3.start();
}

}

2、同步方法

  • 同步方法的格式及锁对象问题?
    把同步的关键字加在方法上
    同步方法的对象是谁呢?
    this.

(3)lock和unlock

Lock:

  •  void lock():获取锁 上锁
    
  •  void unlock():释放锁 放锁
    
  • ReentrantLock 是Lock的实现类

(4)死锁

同步的弊端:

  •  A.效率低
    
  •  B.容易发生死锁
    
  • 死锁:
  •  两个或两个以上的线程在争夺资源的过程中,发生一种相互等待的现象。
    

(5)生产与消费的问题

  • 资源类:Phone
  • 生产类:SetPhone (生产者)
  • 消费类:GetPhone (消费者)
  • 测试类:PhoneDemo

(6)定时器

		定时器是指在指定的时间做某一件事,还可以重复做某件事
		定时器的类分别是Timer和Timertask两个类
  • schedule(TimerTask task, Date firstTime, long period) // Timertask:任务

       从指定 的时间开始 ,对指定的任务执行重复的 固定延迟执行 。  
    

    void schedule(TimerTask task, long delay)

       在指定的延迟之后安排指定的任务执行。  
    

    void schedule(TimerTask task, long delay, long period)
    第一个参数:任务
    第二个参数:延迟多少秒后执行任务
    第三个参数:每隔多少秒后执行任务
    void cancel()

    终止此计时器,丢弃任何当前计划的任务。

猜你喜欢

转载自blog.csdn.net/yz1534194168/article/details/82973253