线程、进程、程序
线程(Thread):一个程序中的一条执行路径,如果有多条路径就是多线程
进程(Process):程序的一次静态的执行的过程
程序(Program):用某种语言编写的一组指令的集合
线程与进程的区别
1.进程是作为分配的单位的,线程是作为调度和执行的单位
2.每个进程都有独立的代码和数据空间,进程间的切换会有较大的开销,而线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小
3.在操作系统中能同时运行多个程序,在同一应用程序中有多个顺序流同时执行
4.系统会给进程分配不同的内存区域,但是线程没有,线程所使用的资源是进程的,共享进程资源
创建线程的三种方式
1.继承Thread类
注意:
1.要重写run()方法
2.不要直接调用run()方法(会被当成普通方法使用,并没有使用线程)
3.用start()方法,启动线程
4.不建议使用这种方式,因为Java是单继承,继承要留给最需要的类
2.实现Runnable接口
注意:
1.重写run()方法
2.该接口没有启动线程的方法,所以想要启动线程就要使类Thread,里面实现了Runnable方法,有可以传入Runnable的构造器
3.这种结构又称代理模式
3.实现Callable接口
子主题 1
锁
1.同步锁(监视器)--Synchronized:
1.线程安全问题一般都出现在多个线程访问同一个资源时
2.锁的类型必须是引用数据类型,但尽量不适用String类型
3.建议使用final修饰同步监视器
同步方法:
1.不要将run直接定义成同步方法
2.非静态的同步方法的同步监视器是this
3.静态的同步方法的同步监视器是 类名.class
4.同步代码块比同步方法的效率高,因为同步代码块只是锁住了,可能会出现抢夺资源的代码块,而同步方法是锁住了整个方法
2.Lock锁
1.Lock锁和synchronize的区别:
~Lock锁是显示锁,需要手动关锁和开锁,synchronized是隐式锁
~Lock只有代码块锁,synchronized有代码块锁和方法锁
~使用Lock锁,JVM只需花费较少的时间来进行调度线程,性能更好,并且具有较好的扩展性
2.优先使用顺序:
Lock---同步代码块---同步方法
线程的一些常用方法
jion()、Sleep()、yiled()
jion()代码示例:
package xiancheng;
public class Jion implements Runnable{
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println("我是傻逼====="+i);
}
}
public static void main(String[] args) {
Jion jion = new Jion();
Thread thread = new Thread(jion);
thread.start();
for (int i = 0; i <100 ; i++) {
/**
* 调用该方法的线程强制执行,其它线程处于阻塞
* 状态,该线程执行完毕后,其它线程再执行;
*/
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"呵呵主线-------"+i);
}
}
}
Sleep()代码示例:
package xiancheng;
public class SleepDemo {
public static void main(String[] args) {
ThreadApiDemo threadApiDemo = new ThreadApiDemo();
Thread thread = new Thread(threadApiDemo);
thread.start();
for (int i = 0; i <10 ; i++) {
//使用当前正在执行的线程休眠millis秒,线程处于阻塞状态(写在那个线程中就是那个休眠),但是不会释放锁
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("呵呵主线程"+i);
}
}
}
yiled()代码示例
package xiancheng;
public class Yield {
public static void main(String[] args) {
ThreadApiDemo threadApiDemo = new ThreadApiDemo();
Thread thread = new Thread(threadApiDemo);
thread.start();
/**
* 当前正在执行的线程暂停一次,允许其他线程执
* 行,不阻塞,线程进入就绪状态,如果没有其他等待
* 执行的线程,这个时候当前线程就会马上恢复执
* 行。
*/
for (int i = 0; i <10 ; i++) {
if (i==2){
Thread.yield();
}else {
System.out.println("呵呵main---="+i);
}
}
}
}
画一下线程的生命周期:
经典例子:买火车票
package com.ThreadTicket;
public class RunnableTicket implements Runnable {
private int ticket=10;
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
if (ticket>0){
System.out.println(Thread.currentThread().getName() + "-----正在卖第" + (ticket--) + "张票");
}
}
}
public static void main(String[] args) {
RunnableTicket runnableTicket = new RunnableTicket();
Thread thread1 = new Thread(runnableTicket,"1号窗口");
Thread thread2 = new Thread(runnableTicket,"2号窗口");
Thread thread3 = new Thread(runnableTicket,"3号窗口");
Thread thread4 = new Thread(runnableTicket,"4号窗口");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}