公司做完网站怎么搜不到,宁波建网站方式,百度公司网站制作,企业做网站建设遇到的问题1 进程 1 进程和线程之间的关系#xff1a;进程是线程的容器。2 线程 1 线程的执行流程#xff1a;
**线程调用start(#xff09;**方法时#xff0c;表示线程开始执行#xff1b;当线程执行时#xff0c;处于RUNNABLE状态#xff0c;表示线程所需的一切资源都准备好了…1 进程 1 进程和线程之间的关系进程是线程的容器。2 线程 1 线程的执行流程
**线程调用start(**方法时表示线程开始执行当线程执行时处于RUNNABLE状态表示线程所需的一切资源都准备好了当线程遇到synchronized同步块就进入BLOCED阻塞状态这时线程会暂停执行直到获得请求的锁。
2 WAITING 和 TIMED_WAITING:
WAITING 和 TIMED_WAITING都表示等待状态区别是WAITING会进入一个无时间限制的等待TIMED_WAITING会进行一个有限的等待。WAITING 的线程是在等待一些特殊事件比如wait(方法等待notify方法join等待目标线程的终止。线程的基本操作 1 注意不要用run开启新线程它只会在当前线程中串行执行run中的代码。 2 创建线程的两种方式实现Runnable接口继承Thread类 //Runnable接口public interface Runable{public abstract void run();4 终止线程
为何终止一般线程会自动终止但是一些服务端的后台线程会常驻系统它们本身是无穷循环用于提供某些服务。 1 使用stop() //未来将被废弃 stop有一个局限性 当写入两个相同的值当线程写到一半并强行终止对象就会被写坏。从而出现 写读不一致的现象。stop发生的问题很难排查除非你很清楚你在干什么否则不要随便使用stop去 终止一个线程 2 自行决定何时退出 1 在自己的线程类中增加一个stopMe方法
ChangeObjectThread extends Threadvolatile Boolean stopme falsepublic void stopMestopme truepublic void runwhiletrueifstopme//退出位置pringtln“exit by stop me”;break//你的代码5 线程中断
什么是线程中断 线程中断不会使线程立即退出而是给线程一个通知告知目标线程有人希望你退出了至于**目标线程接到通知后 如何处理由自己决定。**这点很重要避免了stop那样出现的问题。与线程中断的三种方法 1 Thread.interrupt通知目标线程中断设置中断标志。 2 Thread.isInterrupted检查中断标志判断当前线程是否被中断。 3 Thread.interrupted判断当前线程中断状态但同时会清楚当前线程中断标志位状态。 3 如何操作
mainString[] argsThread t1 new Threadpublic void runwhiletrue//中断处理程序ifThread.currentThread.isInterruptedsysou(Interrupted)break...;Thread.yield//线程让步 t1.startThread.sleep2000t1.interrupt//单单这里中断是没有效果的一定要写入上面的中断处理程序中断的方法比stopme标记手法功能更强劲强劲之处在循环体中出现wait或sleep只能通过中断识别。 Thread.sleep方法会抛出一个InterruptedException中断异常当线程sleep处于休眠时如果被中断异常就会产生。这时会清除中断标记位如果不处理在下次循环中无法捕获到这个中断故在异常处理中再次设置中断标记位
6 等待wait和通知notify
等待wait 当线程A中调用了obj.wait线程A停止继续执行进入现场等待池中等待让出系统资源既让出了锁资源。线程A会一直等到其他线程调用obj.notify位置。obj对象成为多个线程的有效通信手段。wait 和 notify 如何工作 当一个线程调用obj.wait那么它就进入obj的等待队列。这个等待队列可能有多个线程。当obj.notify被调用时它会从等待队列中水机选选择一个线程将其唤醒这里的唤醒是允许其去获得锁。这个选择时随机的。除了notify可以唤醒线程还有notifyAll只是notifyAll唤醒所有的线程而不是一个。注意点 object.wait不是随便调用的必须包含在对应同步语句中无论是wait 还是 notify都需要首先获得目标对象 obj的一个监视器。
public class SimpleWN{public static void main(String[] args) {Thread t1 new T1();Thread t2 new T2();t1.start();t2.start();}final static Object obj new Object();public static class T1 extends Thread{Overridepublic void run() {synchronized (obj) {System.out.println(System.currentTimeMillis() :T1 start! );try {System.out.println(System.currentTimeMillis() :T1 wait for obj);obj.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(System.currentTimeMillis() :T1 end!);}super.run();}}public static class T2 extends Thread{Overridepublic void run() {// TODO Auto-generated method stubsynchronized (obj) {System.out.println(System.currentTimeMillis() :T2 start! notify one thread!);obj.notify();System.out.println(System.currentTimeMillis() :T2 end!);try {Thread.sleep(2000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}super.run();}}
}wait 和 sleep :都是等待若干时间区别是wait可以被唤醒还有wait方法会释放目标对象的锁。而sleep不会。
7 挂起suspend和继续执行resume
被挂起的线程必须等到resume操作后才能继续执行。suspend是被废弃的方法被挂起的线程在导致线程暂停的同时并不会释放任何锁资源。导致其他线程想要访问被它暂用的锁资源都会受牵连。怎样用一种可靠的方式使用suspend 利用wait和notify方法,在应用层实现suspend 和resume 功能。
package com.sean.thread;public class GoodSuspend{public static Object u new Object();public static void main(String[] args) throws InterruptedException {ChangeObjThread t1 new ChangeObjThread();ReadObjThread t2 new ReadObjThread();t1.start();t2.start();Thread.sleep(1000);t1.suspendMe();System.out.println(suspend t1 2 sec);Thread.sleep(20000);System.out.println(resume t1);t1.resumeMe();}public static class ChangeObjThread extends Thread{volatile boolean suspendme false;public void suspendMe(){suspendme true;}public void resumeMe() {suspendme false;synchronized(this){notify();}}Overridepublic void run() {while (true) {synchronized (this) {while (suspendme) {try {wait(); //运用等待实现挂起} catch (InterruptedException e) {e.printStackTrace();}}}synchronized(u){System.out.println(in ChangeObjThread);}Thread.yield();}}}public static class ReadObjThread extends Thread{Overridepublic void run() {while(true){synchronized (u) {System.out.println(in ReadObjThread);}Thread.yield();}}}
}8 等待线程结束join和谦让yield
public final void join() throws InterruptedException
public final synchronized void join(long millis) throws InterruptedExceptionjoin表示无限等待它会一直阻塞当前线程直到目标线程执行完毕。yield给出了一个 最大等待时间如果超过时间就会继续往下执行。 join的本质是调用线程wait在当前线程对象实例上。当线程执行完成后被等待的线程 在退出时调用notifyAll通知所有线程继续执行因此不要在THread对象上使用类似wait、notify等方法可能会影响api工作。 Thread.yield 一旦执行会使当前线程让出CPU。但是并不代表不执行会有一定几率分配到
public class GoodSuspend {public volatile static int i 0;public static class AddThread extends Thread {Overridepublic void run() {for (i 0; i 100000000; i) {}}}public static void main(String[] args) throws InterruptedException {AddThread at new AddThread();at.start();at.join();System.out.println(i);}
}3 volatile 与java内存模型(JMM)
1 java内存模型围绕着原子性、有序性和可见性展开的。但是可以利用关键字或特殊操作告诉虚拟机有些地方需要特别 注意,比如 volatile。 2 volatile
使用 volatile 去申明一个变量时在程序范围内的所有其他线程“可见”的虚拟机就会小心处理这种情况volatile并不能代替锁也无法保证一些复合操作的原子性当两个线程同时修改数据时依然会产生冲突。volatile能保证数据的可见性和有序性。
//volatile无法保证一些复合操作
public class GoodSuspend {static volatile int i 0;public static class PlusTask implements Runnable{Overridepublic void run() {for (int k 0; k 10000; k){i;};}}public static void main(String[] args) throws InterruptedException {Thread[] task new Thread[10];for (int i 0; i 10; i) {task[i] new Thread(new PlusTask());task[i].start();}for (Thread thread : task) {thread.join();}System.out.println(i);}
}4 线程组 和一个篮子一样篮子里的每个水果是线程。
public class ThreadGroupName implements Runnable {static volatile int i 0;public static void main(String[] args) {ThreadGroup tg new ThreadGroup(PrintGroup);Thread t1 new Thread(tg, new ThreadGroupName(), T1); //定义线程并加入到线程组Thread t2 new Thread(tg, new ThreadGroupName(), T2);t1.start();t2.start();System.out.println(tg.activeCount());tg.list();}Override//输出线程信息public void run() {String groupAndName Thread.currentThread().getThreadGroup().getName() Thread.currentThread().getName();while (true) {System.out.println(I am group groupAndName);try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}}
}5 驻守后台守护线程Daemon 守护线程系统的守护者默默完成系统的一些系统性的服务比如垃圾回收线程、JIT线程就可以理解为守护线程。与之相对应的是用户线程系统的工作线程。要在start之前设置守护线程否则抛出异常当成用户线程使用。
Thread t new DaemonT();
t.setDaemon(true); //设置守护线程
t.start();6 线程优先级先做重要的事 优先级越高资源竞争越有优势更可能抢占资源。优先级产生的后果无法精准控制可能出现低优先级一直抢占不到资源一直无法运行从而产生饥饿现象.自己在应用层解决线程调度的问题。 数字越大优先级越高有效范围在1-10。
public class PriorityDemo{public static void main(String[] args) {//高权限和低权限的线程做同一件事HightPriority h new HightPriority();LowPriority l new LowPriority();h.setPriority(Thread.MAX_PRIORITY);//线程设置为高权限l.setPriority(Thread.MIN_PRIORITY);//线程设置为低权限l.start();h.start();}//~做同一件事情总是高权限线程先完成public static class HightPriority extends Thread{static int count 0;public void run(){while(true){synchronized (PriorityDemo.class) {//使用同步产生资源竞争,而权限高低会去竞争锁资源count;if (count 1000000) {System.out.println(HightPriority is complete!);break;}}}}}public static class LowPriority extends Thread{static int count 0;public void run(){while(true){synchronized (PriorityDemo.class) {count;if (count 1000000) {System.out.println(LowPriority is complete!);break;}}}}}
}7 线程安全与synchronized 多线程的写入冲突线程不安全当两个线程同时修改一个共享对象产生覆盖的现象。 比如有一个共享对象int i线程A和线程B都对i 累加10000次我们想要的结果是20000但我们得到的结果总是小于这个值。 即使用volatile这种关键字也是如此因为volatile不能解决两个线程同时修改共享对象的问题。
public class AccountingVol implements Runnable{public static volatile int i 0;Overridepublic void run() {for (int k 0; k 1000000; k) {i;}}public static void main(String[] args) throws InterruptedException {AccountingVol v1 new AccountingVol();Thread t1 new Thread(v1); //此行和下面一行的Runnable实例一定要是同一个这样才能保证在两个线程工作时关注到同一个对象锁上从而保证线程安全。Thread t2 new Thread(v1);t1.start();t2.start();t1.join(); //主线程愿意等到该线程执行完再执行t2.join();System.out.println(i);}
}使用 synchronized 来解决线程安全的问题 用法: 指定加锁对象对给定对象加锁进入同步代码前要获得给定对象的锁。直接作用于实例对象相当于对当前实例加锁…。直接作用于静态方法相当于对当前类加锁进入同步块要获得当前类的锁。 当线程进入被synchronized包裹的代码块必须先请求锁如果有其他线程正在持有这把锁则新到的线程就必须等待。
//将上例中的run加上一个同步块
synchronized (v1) { //同步块只有一个持有锁的线程可进入for (int k 0; k 1000000; k) {i;}
}可将synchronized关键字作用于一个实例方法意思是进入该方法前线程需获得当前对象实例的锁。
//上面同步块代码转为一个方法这种事获取当前对象实例的锁
public synchronized void increase(){i;
}
for (int k 0; k 1000000; k) {this.increase();
}
想要保证两个线程的线程安全必须要两个线程都指向同一个Runnable实例接口这样才能使两个线程关注到同一个对象锁上既要使用同一把锁才能保证线程安全使用下面方法也可以正确执行。
//这样使用的是当前类的锁即使不是同一个Runnable对象也可以正确执行
public static synchronized void increasei8 程序中的幽灵隐藏的错误 案例比如两个数相加导致int的溢出就会导致出现负数的情况 并发下的 ArrayListArrayList 是不安全的可用 Vector 代替 ArrayList 并罚下的诡异的 HashMap 可能有三种情况 1 程序正常结束2 程序正常结束不符合预期 3 程序死循环链表遭到破坏链表成环 错误的加锁 最好别加在Integer对象上Integer对象在做运算时是创建一个新的Integer对象的String对象也是如此。