多线程
进程:观察任务管理器,发现正在运行的程序(桌面的应用程序,客户端程序..)就是一个进程。
进程来说:进程是系统分配资源调用的一个独立单位。
线程:线程是依赖于进程存在,一个线程相当于进程中的某个任务。
多线程的意义:
一个进程中开启了多个任务,每个一任务(线程),他们在互相抢占CPU的执行权,(提高程序的执行效率)
多线程在抢占CPU的执行权:特点:具有随机性!
是多线程程序,由于java虚拟机中自带一个垃圾回收器,来确保程序不会轻易的造成内存溢出!
至少开启两条子线程:
当前程序在执行代码的时候,会开启main:主线程
垃圾回收器会开启一个垃圾回收线程,来确保程序不会内存异常,将不用的变量或者没有更多引用的对象来回收掉。
多线程的实现方法
方法一:
1)自定一个类:MyThread 继承自Thread类
2)在MyThread类中重写Thread类中的run()
3)在主线程中,创建该类的实例对象,启动线程
package prac;
public class Prac01 {
public static void main(String[] args) {
MyThread my1=new MyThread();
MyThread my2=new MyThread();
//无参构造设置线程名称
my1.setName("a");
my2.setName("b");
my1.start();
my2.start();
//获取当前正在执行的线程的名称:main
System.out.println(Thread.currentThread().getName());
}
}
package prac;
public class MyThread extends Thread {
public MyThread(){
}
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + ":" + i);
}
}
}
一些方法:
1)public final void join()
throws InterruptedException等待该线程终止。
当前线程执行完才能执行其他线程。
(设置线程等待该线程终止该方法必须要启动线程)
2) public final int getPriority()返回线程的优先级。
默认优先级:5
public static final int MAX_PRIORITY 10 :最大优先级(优先级大的抢占到CPU的执行权大,并不代表就一定能抢到,因为线程的执行具有随机性!)
public static final int MIN_PRIORITY 1 :最小优先级
public static final int NORM_PRIORITY 5 :默认优先级
3)public static void yield()暂停当前正在执行的线程对象,并执行其他线程。
暂停当前线程执行其他线程,并不保证另一个线程就一定能抢占到CPU的执行权。
4)public final void setDaemon(boolean on) on指定true,就是设置守护线程…
jvm自动退出,对于主线程的数据如果直接输出完毕,对于两个守护线程来说不会立即消失,Jvm等会就自动退出.(启动线程前调用)
package prac;
public class Prac01 {
public static void main(String[] args) {
MyThread my1=new MyThread();
MyThread my2=new MyThread();
//无参构造设置线程名称
my1.setName("a");
my2.setName("b");
//设置守护线程
my1.setDaemon(true);
my2.setDaemon(true);
my1.start();
my2.start();
//主线程
Thread.currentThread().setName("AB");
//获取当前正在执行的线程的名称:main
for(int x=0;x<6;x++){
System.out.println(Thread.currentThread().getName());
}
}
}
5)线程睡眠:
public static void sleep(long millis)
throws InterruptedException在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
6) 线程停止:
public final void stop():强迫线程停止执行
public void interrupt()中断线程。 表示中断线程一种状态
方法二:
实现Runnable接口
package prac;
public class Prac02 {
public static void main(String[] args) {
MyRunnable my = new MyRunnable() ;
//public Thread(Runnable target,String name)
Thread th1=new Thread(my,"a");
Thread th2=new Thread(my,"b");
th1.start() ;
th2.start() ;
}
}
package prac;
public class MyRunnable implements Runnable {
@Override
public void run() {
for(int i=0;i<100;i++){
//间接的使用Thread类的静态功能得到线程名称
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
线程安全
检验多线程安全问题的标准:
1)当前是否是一个多线程环境
2)多线程环境中是否有共享数据
3)是否有多条语句对共享数据进行操作
Java的同步机制:
使用同步代码块:synchronized(同步锁对象){
多条语句对共享数据的操作;
}
package prac;
public class Prac04 {
public static void main(String[] args) {
SellTickets st=new SellTickets();
Thread th1=new Thread(st,"窗口一");
Thread th2=new Thread(st,"窗口二");
Thread th3=new Thread(st,"窗口三");
th1.start();
th2.start();
th3.start();
}
}
package prac;
public class SellTickets implements Runnable {
private int tickets = 100;
private Object obj = new Object();
public void run() {
while (true) {
//同步机制
synchronized (obj) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + tickets-- + "张票");
}
}
}
}
}
package prac;
public class SellTickets implements Runnable {
private int tickets = 100;
public void run() {
while (true) {
sellTickets();
}
}
//同步方法
private synchronized void sellTickets() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + tickets-- + "张票");
}
}
}