线程和多线程
- 进程:正在运行的程序
- 线程: 进程中的一个小任务,线程是进程的一个执行单元,来完成进程中的某一个功能
- 一个程序运行后至少有一个进程,一个进程可以包含多个线程
- 单线程程序:若有多个任务只能依次执行,当上一个任务执行结束后,下一个任务开始执行
- 多线程程序:多个任务可以同时执行
- 分时调度:所有线程轮流使用cpu使用权,平均分配每个线程占用cpu空间
- 抢占式调度:优先让优先级高的线程使用cpu,如果线程优先级相同,则会随机选择一个
- 多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让cpu的使用率更高
- main方法所在线程称为主线程
- 同一个主线程中的代码指令按顺序执行,一般不能跳过,原因是:jvm启动后,必然有一个执行路径从main方法开始的,一直执行到main方法结束。当程序的主线程执行时,如果遇到了循环而导致程序在指定的位置停留时间过长,则无法马上执行下面程序,需要等待循环结束后能够执行
Thread类
-
构造:public Thread()//创建一个默认名字的线程 public Thread(String name)创建一个指定名字的线程
-
开启线程的第二种方法:声明实现Runnable接口的类,该类然后实现run方法,然后可以分配该类的实例,在创建Thread时候作为一个参数来传递并启动
-
创建线程方式一:继承方式
-
class 子线程类 extends Thread{
run(){
任务代码
}
}
-
- 子线程类 t = new 子线程类();
- t.start();
- 创建线程方式二:实现方式
-
class 实现类 implements Runnable{
run(){
}
}
-
Thread t = new Thread(new 实现类());
-
t.start();
-
从耦合性分析:
- 第一种方式:线程和任务紧密结合,耦合性高
- 第二中方式:线程和任务之间没有必然联系
-
从代码扩展性分析:
- 第一种方式,由于是继承Thread,那么子线程类就不能继承别的类
- 第二种方式,由于是实现了接口,同时可以继承别的类
-
匿名内部类:快速创建一个类的子类对象,或者一个接口的实现类对象
-
new 父类(){
重写方法
}
-
new 接口(){
实现方法
}
-
使用匿名内部类创建线程对象
new Thread(){ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("匿名内部类线程"+ i); } } }.start();
-
实现方式
//实现方式 Runnable run = new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("第二种线程"+i); } } }; new Thread(run).start();
-
-
线程安全:当有多个线程同时运行,这些线程必须执行同一个代码,操作同一个共享数据时,可能出现线程的安全问题
-
实战:买票的问题
public class TicketsRunnable implements Runnable { private int count = 1000; @Override public void run() { //the task is to 100 tickets while (true){ if(count > 0){ try{Thread.sleep(50);}catch (Exception e){} System.out.println("卖出第"+ count+ "票"); count--; } } } } package java学习.Threadings; public class SaleTicketsDemo { public static void main(String[] args) { //create a buy tickets task object TicketsRunnable tr = new TicketsRunnable(); //create three thread object to perform task Thread t1 = new Thread(tr); t1.start(); Thread t2 = new Thread(tr); t2.start(); Thread t3 = new Thread(tr); t3.start(); } } 运行会出现问题,出现问题的原因是多个线程相互切换的时间互不相同,同时count的值也存在很大不确定性
-
解决线程安全问题方式一:
-
给代码加上锁
synchronized(对象){
代码
}锁对象可以是任何对象
synchronized (obj){ while (true){ if(count > 0){ try{Thread.sleep(50);}catch (Exception e){} System.out.println("卖出第"+ count+ "票"); count--; } }
-
同步方法
public synchronized void 方法名(){
}
同步方法的使用原理和1方法一样,只不过它的对象是this;如果同步方法是静态方法,那么他的对象是类
-
lock接口实现类:Reentrantlock实现类
在lock接口中有两个方法:lock() unlock()
-
线程状态码: