进程是系统进行资源管理的基本单位;java
线程是进程中独立的子任务安全
在使用多线程技术时,代码的运行结果与代码执行顺序或调用顺序是无关的多线程
java是单继承不支持多继承,因此有runnable接口dom
线程不共享数据:ide
public class MyThread extends Thread {测试
private int count = 5;this
public MyThread(String name) {spa
super();线程
this.setName(name);对象
}
public void run() {
super.run();
while (count > 0) {
count--;
System.out.println("--" + this.currentThread().getName() + "count" + count);
}
}
}
public class Run {
public static void main(String[] args) {
MyThread a = new MyThread("A");
MyThread b = new MyThread("B");
MyThread c = new MyThread("C");
a.start();
b.start();
c.start();
}
}
线程间共享数据
public class MyThread extends Thread {
private int count = 5;
public MyThread(String name) {
super();
this.setName(name);
}
public void run() {
super.run();
while (count > 0) {
count--;
System.out.println("--" + this.currentThread().getName() + "count" + count);
}
}
}
public class Run {
public static void main(String[] args) {
MyThread mythread = new MyThread();
Thread a = new Thread(mythread, "A");
Thread b = new Thread(mythread, "B");
Thread c = new Thread(mythread, "C");
Thread d = new Thread(mythread, "D");
Thread e = new Thread(mythread, "E");
a.start();
b.start();
c.start();
d.start();
e.start();
}
}
非线程安全:
public class LoginServlet {
private static String usernameRef;
private static String passwordRef;
public static void doPost(String username,String password){
try {
usernameRef=username;
if(username.equals("a")){
Thread.sleep(5000);
}
passwordRef=password;
System.out.println("username="+usernameRef+"password"+password);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ALogin extends Thread {
@Override
public void run() {
LoginServlet.doPost("a", "aa");
}
}
public class BLogin extends Thread {
@Override
public void run() {
LoginServlet.doPost("b", "bb");
}
}
public class Run {
public static void main(String[] args) {
ALogin a = new ALogin();
a.start();
BLogin b = new BLogin();
b.start();
}
}
线程安全 加synchronized,使线程排队进入
public class MyThread extends Thread {
private int i = 5;
public void run() {
System.out.println("i=" + (i--) + "threadName=" + Thread.currentThread().getName());
}
}
public class Run {
public static void main(String[] args) {
MyThread run = new MyThread();
Thread r1 = new Thread(run);
Thread r2 = new Thread(run);
Thread r3 = new Thread(run);
Thread r4 = new Thread(run);
Thread r5 = new Thread(run);
r1.start();
r2.start();
r3.start();
r4.start();
r5.start();
}
}
println()在内部是同步的,可是i—的操做是在这个方法以前进行的,有发生非线程安全问题的几率
了解currentThread
public class CountOperate extends Thread {
public CountOperate() {
System.out.println("CountOperate--begin");
System.out.println("Thread.currentThread().getname()=" + Thread.currentThread().getName());
System.out.println("this.getname()="+this.getName());
System.out.println("CountOperate--end");
}
public void run(){
System.out.println("run--begin");
System.out.println("Thread.currentThread().getname()=" + Thread.currentThread().getName());
System.out.println("this.getname()="+this.getName());
System.out.println("run--end");
}
}
public class Run {
public static void main(String[] args) {
CountOperate c = new CountOperate();
Thread t1 = new Thread(c);
t1.setName("A");
t1.start();
}
}
方法isAlive()测试程序是否处于活动状态
public class CountOperate extends Thread {
public CountOperate() {
System.out.println("CountOperate--begin");
System.out.println("Thread.currentThread().getname()=" + Thread.currentThread().getName());
System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
System.out.println("this.getname()="+this.getName());
System.out.println("this.isAlive()="+this.isAlive());
System.out.println("CountOperate--end");
}
public void run(){
System.out.println("run--begin");
System.out.println("Thread.currentThread().getname()=" + Thread.currentThread().getName());
System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
System.out.println("this.getname()="+this.getName());
System.out.println("this.isAlive()="+this.isAlive());
System.out.println("run--end");
}
}
public class Run {
public static void main(String[] args) {
CountOperate c=new CountOperate();
Thread t1=new Thread(c);
System.out.println("main begin t1 s Alive="+t1.isAlive());
t1.setName("A");
t1.start();
System.out.println("main end t1 isAlive="+t1.isAlive());
}
}
Sleep()方法是在指定的毫秒数内让当前“正在执行的线程”休眠,这个“正在执行的线程”是指this.currentThread()返回的线程。
getId()是获取线程的惟一标识
public class Test {
public static void main(String[] args) {
Thread runThread = Thread.currentThread();
System.out.println(runThread.getName() + "---" + runThread.getId());
}
}
中止线程
public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(2000);
thread.interrupt();
}
}
调用interrupt方法并无中止线程,如何中止线程呢
this.interrupted():测试当前线程是否已经中断,当前线程是指运行this.interrupted()方法的线程;
public class Run2 {
public static void main(String[] args) {
Thread.currentThread().interrupt();
System.out.println("是否中止1?" + Thread.interrupted());
System.out.println("是否中止2?" + Thread.interrupted());
System.out.println("end");
}
}
结果:
是否中止1?true
是否中止2?false
end
为何第二次中断判断的时候结果为false呢,这是由于interrupted方法将中断的状态清除了,第二次拿不到中断的状态,因此返回false;
this.isINterrupted():测试线程Thread对象是否已经中断状态,但不清楚状态标识
public class MyThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
for (int i = 0; i < 50000; i++) {
if (this.interrupted()) {
System.out.println("已是中止状态了,我要退出了");
break;
}
System.out.println("i=" + (i + 1));
}
}
}
public class MyThread extends Thread {
@Override
public void run() {
super.run();
try {
for (int i = 0; i < 500000; i++) {
if (this.interrupted()) {
System.out.println("已是中止状态,我要退出了!");
throw new InterruptedException();
}
System.out.println("i=" + (i + 1));
}
System.out.println("我在for下面");
} catch (Exception e) {
System.out.println("进入MyThread.java类run方法中的Catch了!");
e.printStackTrace();
}
}
}
在沉睡中中止
public class MyThread extends Thread {
public void run() {
super.run();
try {
for (int i = 0; i < 1000; i++) {
System.out.println("i =" + (i + 1));
}
System.out.println("run begin");
Thread.sleep(200000);
} catch (Exception e) {
System.out.println("sleep进入Catch!");
}
}
}
暴力中止线程
public class MyThread extends Thread{
private int i=0;
@Override
public void run() {
// TODO Auto-generated method stub
try {
while(true){
i++;
System.out.println("i="+i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread thread=new MyThread();
thread.start();
Thread.sleep(8000);
thread.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
}
方法stop()和java.lang.ThreadDeath异常
public class MyThread extends Thread{
@Override
public void run() {
try {
this.stop();
} catch (ThreadDeath e) {
System.out.println("catch fang fa ");
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
若是强制让线程中止则可能使一些清理工做得不到完成,另一种状况就是对锁定的对象进行了”解锁”,致使数据得不到同步处理,获得不一致的状况。
释放锁的不良后果
使用stop()释放锁将会给数据形成不一致的结果
public class SynchronizedObject {
private String username = "a";
private String password = "aa";
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
synchronized public void printString(String username, String password) {
try {
this.username = username;
Thread.sleep(100000);
this.password = password;
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class MyThread extends Thread {
private SynchronizedObject object;
public MyThread(SynchronizedObject object) {
super();
this.object = object;
}
@Override
public void run() {
object.printString("b", "bb");
}
}
public class Run {
public static void main(String[] args) {
try {
SynchronizedObject object = new SynchronizedObject();
MyThread thread = new MyThread(object);
thread.start();
Thread.sleep(200);
thread.stop();
System.out.println(object.getUsername() + ":" + object.getPassword());
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果:
b:aa
强制stop形成数据不一致;
不建议使用stop()方法
使用return中止线程
使用interrupt()与return结合实现中止线程的效果
暂停线程
suspend与resume方法
public class MyThread extends Thread {
private long i = 0;
public long getI() {
return i;
}
public void setI(long i) {
this.i = i;
}
@Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
while (true) {
i++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(1000);
// A段
thread.suspend();
System.out.println("A=" + System.currentTimeMillis() + "i=" + thread.getI());
Thread.sleep(1000);
System.out.println("A=" + System.currentTimeMillis() + "i=" + thread.getI());
// B段
thread.resume();
Thread.sleep(1000);
// C段
thread.suspend();
System.out.println("B=" + System.currentTimeMillis() + "---i=" + thread.getI());
Thread.sleep(1000);
System.out.println("B=" + System.currentTimeMillis() + "---i=" + thread.getI());
} catch (Exception e) {
e.printStackTrace();
}
}
}
suspend与resume方法的缺点-独占
公共的同步对象的独占,其余线程没法访问公共同步对象
public class Run {
public static void main(String[] args) {
try {
final SynchronizedObject object = new SynchronizedObject();
Thread thread1 = new Thread() {
public void run() {
object.printString();
}
};
thread1.setName("a");
thread1.start();
Thread.sleep(1000);
Thread thread2 = new Thread() {
public void run() {
System.out.println("thread2启动了,但进不了printString()方法!只打印一个begin");
System.out.println("由于printSring()方法被线程a锁定而且永久suspend暂停了");
object.printString();
}
};
thread2.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class SynchronizedObject {
synchronized public void printString() {
System.out.println("begin");
if (Thread.currentThread().getName().equals("a")) {
System.out.println("a线程永远suspend 了!");
Thread.currentThread().suspend();
}
System.out.println("end");
}
}
结果
begin
a线程永远suspend 了!
thread2启动了,但进不了printString()方法!只打印一个begin
由于printSring()方法被线程a锁定而且永久suspend暂停了
suspend方法已经被做废
suspend和resume方法缺点—不一样步
public class MyObject {
private String username = "1";
private String password = "11";
public void setValue(String u, String p) {
this.username = u;
if (Thread.currentThread().getName().equals("a")) {
System.out.println("暂停线程a");
Thread.currentThread().suspend();
}
this.password = p;
}
public void printUsernamePaasword() {
System.out.println(username + ":" + password);
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
final MyObject myobject = new MyObject();
Thread thread1 = new Thread() {
public void run() {
myobject.setValue("a", "aa");
;
};
};
thread1.setName("a");
thread1.start();
Thread.sleep(500);
Thread thread2 = new Thread() {
public void run() {
myobject.printUsernamePaasword();
};
};
thread2.start();
}
}
结果:
暂停线程a
a:11
yield方法
yield()方法的做用是放弃当前的Cpu资源,将它让给其余的任务去占用Cpu执行时间,
但放弃的时间不肯定,有可能刚刚放弃,又立刻得到了Cpu时间片
public class MyThread extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
int count = 0;
for (int i = 0; i < 500000; i++) {
Thread.yield();
count = count + (i + 1);
}
long endTime = System.currentTimeMillis();
System.out.println("用时:" + (endTime - beginTime) + "毫秒!");
}
}
public class Run {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
当有Thread.yield()时,结果:用时:80毫秒!
当没有Thread.yield()时,结果:用时:1毫秒!
线程的优先级
cpu优先执行优先级较高的线程对象中的任务
setPriority()
线程优先级的继承特性
线程的优先级具备继承性,并入A线程启动B线程,则B线程的优先级与A是同样的。public class MyThread1 extends Thread {
@Override
public void run() {
super.run();
System.out.println("MyThread1 run priority=" + this.getPriority());
MyThread2 thread2 = new MyThread2();
thread2.start();
}
}
public class MyThread2 extends Thread {
@Override
public void run() {
System.out.println("MyThread2 run priority=" + this.getPriority());
}
}
public class Run {
public static void main(String[] args) {
System.out.println("main thread begin priority=" + Thread.currentThread().getPriority());
Thread.currentThread().setPriority(6);
System.out.println("main thread end priority=" + Thread.currentThread().getPriority());
MyThread1 thread1 = new MyThread1();
thread1.start();
}
}
运行结果:main thread begin priority=5
main thread end priority=5
MyThread1 run priority=5
MyThread2 run priority=5
线程的优先级具备规则性,也就是CPU尽可能将执行的资源让给优先级比较高的线程,谁先执行和代码的调用顺序无关
public class MyThread1 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
long addResult = 0;
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 5000; i++) {
Random random = new Random();
random.nextInt();
addResult = addResult + i;
}
}
long endTime = System.currentTimeMillis();
System.out.println("★ ★ ★ ★ ★ thread 1 use time= " + (endTime - beginTime));
}
}
public class MyThread2 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
long addResult = 0;
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 5000; i++) {
Random random = new Random();
random.nextInt();
addResult = addResult + i;
}
}
long endTime = System.currentTimeMillis();
System.out.println("☆ ☆ ☆ ☆ ☆ thread 2 use time= " + (endTime - beginTime));
}
}
public class Run {
public static void main(String[] args) {
testB();
}
private static void testA() {
for(int i=0;i<5;i++){
MyThread1 thread1=new MyThread1();
thread1.setPriority(10);
thread1.start();
MyThread2 thread2=new MyThread2();
thread2.setPriority(1);
thread2.start();
}
}
private static void testB() {
for(int i=0;i<5;i++){
MyThread1 thread1=new MyThread1();
thread1.setPriority(1);
thread1.start();
MyThread2 thread2=new MyThread2();
thread2.setPriority(10);
thread2.start();
}
}
}
优先级具备随机性,优先级较高的线程不必定每一次都先执行完,与代码的顺序无关
守护线程
java线程中有两种线程:用户线程和守护线程
守护线程具备“陪伴”意思,当不存在非守护线程时,守护线程自动销毁,典型的守护线程就是垃圾回收线程。
public class MyThread extends Thread {
private int i = 0;
@Override
public void run() {
try {
while(true){
i++;
System.out.println("i="+(i));
Thread.sleep(200);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.setDaemon(true);
thread.start();
Thread.sleep(1000);
System.out.println("wuThread out!");
} catch (Exception e) {
// TODO: handle exception
}
}
}
result
i=1
i=2
i=3
i=4
i=5
wuThread out!