目录
进程与线程
进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,竞争计算机系统资源的基本单位.
线程:是进程的一个执行单元,是进程内科调度实体,比进程更小的独立运行的基本单位.线程也被称为轻量级进程.
一个程序至少一个进程,一个进程至少一个线程.
注:一个线程只属于一个进程,但是一个进程可以拥有多个线程,但至少一个线程.
多线程
多线程是指一个进程同时存在多个执行体,按照几条不同的执行线索共同工作的情况.
创建线程:
方法一:继承Thread类
class MyThread extends Thread {
//重写run方法
@Override
public void run (){
//封装线执行的操作,例如:
System.out.println(getName());
}
}
class myThreadDemo {
public static void main(String[] args) {
// myThread mt1 = new myThread();
// myThread mt2 = new myThread();
// mt1.setName("1");
// mt2.setName("2");
//创建对象时设置线程名称
myThread mt1 = new myThread("1");
myThread mt2 = new myThread("2");
//调用start方法,启动线程
mt1.start();
mt2.start();
}
方法说明:
start ( ) : 启动当前线程,调用当前线程的run ( ) 方法.
run ( ) : 需要重写Thread类中的此方法,将创建线程需要执行的操作声明在此方法中.
currentThread ( ) : 返回执行当前代码的线程对象的引用.
getName ( ) : 获取当前线程的名字.
setName (String name) : 设置当前线程的名字.
getPriority ( ) : 获取线程优先级.
setPriority ( ) : 设置线程优先级,优先级最高为10,默认为5,最低为1.优先级高的线程抢占到CPU执行权的概率高.
join ( ) : 在线程a中调用线程b的join ( ) ,此时线程a就会进入阻塞状态,直到线程b完全执行完之后,线程a再结束阻塞状态.
sleep (int millitime) : 让当前线程"睡眠"(停止执行)指定的毫秒数,在指定的毫秒时间内,当前线程是阻塞状态.
setDaemon (boolean on) : 设置线程为守护线程,当运行的线程均为守护线程时,Java虚拟机将退出.
方法2:实现Runnable接口
class MyRunnable implements Runnable {
//重写run方法
@Override
public void run() {
//封装线程执行的操作
}
}
}
class MyRunableDemo {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
// Thread t1 = new Thread(mr);
// Thread t2 = new Thread(mr);
// t1.setName("1");
// t2.setName("2");
Thread t1 = new Thread(mr,"1");
Thread t2 = new Thread(mr,"2");
t1.start();
t2.start();
}
}
实现Runnable接口相对于继承Thread类的好处:
1.避免了Java单继承的局限性.
2.适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码,数据有效隔离,较好体现了面向对象的设计思想.
线程的生命周期
新建:线程已创建,尚未调用start()方法启动之前.
就绪:新建线程调用start()方法,或是阻塞线程的sleep()方法时间到或其他阻塞方式结束,进入就绪状态,此时线程有执行资格,但无执行权.
运行:此时线程得到CPU的执行权,既有执行资格,又有执行权,线程运行.
阻塞:线程被sleep()或其他阻塞式方法阻塞,此时线程既无执行资格,也无执行权,进入阻塞状态.
死亡:线程run()方法结束,线程死亡.
同步
当多个线程同时操作一个可共享的资源变量时,将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,不被其他线程调用,从而保证了该可共享资源变量的唯一性和准确性.
1.使用synchronized关键字修饰代码块
格式:synchronized (Object o) { 需要被同步的代码块 },锁的对象是括号里的对象.
class SellTicket implements Runnable{
private int tickets = 100;
private Object obj = new Object();
@Override
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()+"售出第"+(101-tickets)+"张票");
tickets--;
}
}
}
}
}
2.使用synchronized关键字修饰非静态方法
格式:修饰符 synchronized 返回值类型 方法名 ( ) { },锁的对象是this.
class SellTicket implements Runnable{
private int tickets = 100;
@Override
public void run() {
while(true) {
sell();
}
}
private synchronized void sell () {非静态方法 锁的对象是this
if(tickets>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"售出第"+(101-tickets)+"张票");
tickets--;
}
}
}
3.使用synchronized关键字修饰静态方法
格式:修饰符 static synchronized 返回值类型 方法名 ( ) { },锁的对象是本类类名.class
class SellTicket implements Runnable{
private static int tickets = 100;
@Override
public void run() {
while(true) {
sell();
}
}
private static synchronized void sell() {//静态方法 锁的对象是SellTicket.class
if(tickets>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"售出第"+(101-tickets)+"张票");
tickets--;
}
}
}
4.Lock锁
void lock ( ) : 获得锁.
void unlock ( ) : 释放锁.
使用try...finally来保证锁的成功释放
class SellTicket implements Runnable {
private int tickets = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
lock.lock();// 获得锁
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售出第" + (101 - tickets) + "张票");
tickets--;
}
} finally {
lock.unlock();// 释放锁
}
}
}
}