代码:即文本文件,是静态的。
程序:代码在内存中运行,是动态的。
进程与线程:
创建状态:线程对象一旦创建就进入到新生状态
就绪状态:调用start方法后,线程立即进入就绪状态,但不意味着立即调度执行
运行状态:由cpu分配到资源,才进入运行状态,真正执行线程的代码块
阻塞状态:当调用sleep、wait或同步锁定时,线程进入阻塞状态。此时,代码不往下执行,阻塞事件解除后,重新进入就绪状态,等待cpu调度执行
死亡状态:线程中断或结束,一旦进入死亡状态,就不能再次启动
1)继承Thread类
2)实现Runnable接口
3)通过Callable和Future创建
//更改线程的优先级
setPriority(int new Priority)
//在指定的毫秒数内让当前正在执行的线程休眠
static void sleep(long millis)
//等待该线程终止
void join()
//暂停当前正在执行的线程对象,并执行其它线程
static void yield()
//中断线程,别用该方式
void interrupt()
//测试线程是否处于活动状态
boolean isAlive()
不推荐使用JDK提供的stop()、destroy()方法。已废弃。
推荐线程自己停止下来——>利用次数,不建议死循环,即使死循环也应该添加延时。
建议使用一个标志位进行终止变量。当flag=false时,终止线程运行。
private boolean flag=true;
public void(){
while(flag){}
}
public void stop(){
this.flag=false;
}
//每秒输出系统时间
public class SleepDemo {
public static void main(String[] args) {
Date date = new Date(System.currentTimeMillis());
while(true){
try {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
date = new Date(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class YieldDemo {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程停止执行");
}
}
public class JoinDemo implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println("线程vip来了"+i);
}
}
public static void main(String[] args) throws InterruptedException {
JoinDemo joinDemo = new JoinDemo();
Thread thread = new Thread(joinDemo);
thread.start();
for(int i=0;i<1000;i++){
if(i==200){
thread.join();
}
System.out.println("main--"+i);
}
}
}
NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
public class StateDemo{
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
for(int i=0;i<5;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//观察状态
Thread.State state = thread.getState();
System.out.println(state);//NEW
//观察启动后
thread.start();
state = thread.getState();
System.out.println(state);
while(state!=Thread.State.TERMINATED){
Thread.sleep(100);
state = thread.getState();
System.out.println(state);//输出状态
}
}
}
先设置优先级,再启动
优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,这都是看cpu的调度
//守护线程
public class DaemonDemo {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true);//默认是false,表示是用户线程
thread.start();//守护线程启动
new Thread(you).start();
}
}
//上帝
class God implements Runnable{
@Override
public void run() {
while(true){
System.out.println("上帝保护着你");
}
}
}
//个人
class You implements Runnable{
@Override
public void run() {
for(int i=0;i<36500;i++){
System.out.println("你,开心的活着"+i);
}
System.out.println("good bye!world");
}
}
并发:同一个对象被多个线程同时操作
抢票事件&取钱事件&厕所
处理多线程问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象。这时候我们就需要线程同步。线程同步其实就是等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用
队列和锁
由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制synchronized,当一个线程获得对象的排它锁,独占资源,其它线程必须等待。
使用后释放锁即可,存在以下问题:
由于我们可以通过private关键字来保证数据对象只能被方法访问,所以只需 要对方法提出一套机制,这套机制就是synchronized关键字,它包括两种方法:synchronized方法和synchronized块
public synchronized void method(){}
synchronized方法控制对“对象”的访问,每个对象对应一把锁,每个synchronized方法都必须获取调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行
缺陷:若将一个大的方法声明为synchronized将会影响效率
synchronized(Ojb){}
Obj称之为同步监视器
同步监视器的执行过程
锁的是需要变化的量
多个线程各自占有一些共享资源,并且互相等待其它线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形。
某一个同步块同时拥有两个以上对象的锁时,就可能会发生死锁的问题
产生死锁的四个必要条件:
只要想办法破坏其中的任意一个或多个条件,就可以避免死锁发生
原文:https://www.cnblogs.com/heibaimao123/p/13770615.html