多线程编程(进程和线程)
1.进程:指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程可以启动多个线程。
2.线程:指程序中一个执行流程,一个进程中可以运行多个线程。
一、创建线程(两种方式)
二、线程的5种状态( New,Runnable,Running,Block,Dead ):
三、线程的优先级
四、守护线程 /精灵线程/后台线程
五、方法
六、同步代码锁(synchronized)
一、创建线程(两种方式):
方式1:采用继承Thread的方法
第一,继承 Thread 类
第二,覆盖 run 方法(就是更新运行过程), 实现用户自己的过程
第三,创建线程实例(就是创建一个线程)
第四,使用线程实例的 start() 方法启劢线程, 启劢以后线程会尽快的去并发执行 run()
public class Mythread extends Thread {
@Override
public void run() {
for (int i = 0; i <100; i++) {
System.out.println("hello"+i);
yield();
}
}
}
Mythread my1=new Mythread();
my1.start();
方式2:采用实现Runnable的方法
public class MyThread2 implements Runnable {
int tickets = 10;
@Override
public void run() {
for (int i = 0; i <10; i++) {
if (this.tickets > 0){
System.out.println(Thread.currentThread().getName() + "出售车票"
+ tickets--);
}
}
}
}
二、线程的5种状态( New,Runnable,Running,Block,Dead ):
1. New 新建状态:
new 关键字创建了一个线程后,该线程就处于新建状态,调用 start()方法时,线程启劢,迚入 Runnable 状态
2. Runnable 可运行(就绪)状态:
Runnable 状态时,表示线程准备就绪,等待获取 CPU
3.Running 运行(正在运行)状态:
线程获取了 CPU,则迚入 Running 状态
4.Block 阻塞(挂起)状态
线程调用了 sleep()方法,线程调用了一个阻塞式 IO 方法时被阻塞,当阻塞结束时,该线程将迚入 Runnable 状态
5.Dead 死亡状态
当线程的 run()方法执行结束,线程迚入 Dead 状态
三、线程的优先级
(资源紧张时候, 尽可能优先)setPriority()最高级别为10,最低级别为1,默认级别为5
Mythread my1=new Mythread();
Mythread2 my2=new Mythread2();
my1.setPriority(10);//设置线程的优先级(资源紧张时候,尽可能优先)
my2.setPriority(1);
将my1的优先级设为10,my2的优先级设为1,多的代表优先被执行
四、守护线程 /精灵线程/后台线程
setDaemon();只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。Java 过程的结束:当前所有前台线程都结束时, Java 过程结束,当前台线程结束时,不管后台线程是否结束, 都要被停掉!
Thread2 t2=new Thread2();
t2.setDaemon(true);
五、方法
5.1:join();
thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。 join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。
Mythread my1=new Mythread();
Mythread2 my2=new Mythread2();
my1.start();
my1.join();//先执行完my1,再执行下面的
my2.start();
5.2:sleep(long millis) ;
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
public void run() {
for (int i = 0; i < 30; i++) {
synchronized (this) {// 同步代码块
if (tickets > 0) {
System.out.println(Thread.currentThread().getName()
+ "出售车票" + tickets--);
}
}
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
}
}
5.3:yield();
暂停当前正在执行的线程对象,并执行其他线程。 一般写在重写方法里面
@Override
public void run() {
for (int i = 0; i <100; i++) {
System.out.println("yes"+i);
yield();
}
}
5.4:setName();
改变线程名称,使之与参数 name 相同。
Thread1 t1=new Thread1();
t1.setName("主线程");
六、同步代码锁(synchronized)
1、异步:并发, 各干自己的。
2、同步:步调一致的处理。
多个线程并发读写同一个临界资源时候会发生”线程并发安全问题。
常见的临界资源:
1、多线程共享实例变量
2、静态公共变量
6、1 同步方法:要使用临界资源的位置加锁
int tickets=20;
public void run() {
for (int i = 0; i <20; i++) {
sale();
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
}
}
public synchronized void sale(){//创建方法,加synchronized关键字
if(tickets>10){
System.out.println(Thread.currentThread().getName()+"出售车票"+tickets--);
}
}
6、2 同步代码块的方式:synchronized();
int tickets = 20;
@Override
public void run() {
for (int i = 0; i < 30; i++) {
synchronized (this) {// 同步代码块
if (tickets > 0) {
System.out.println(Thread.currentThread().getName()
+ "出售车票" + tickets--);
}
}
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
}
}