進程是系統進行資源管理的基本單位;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!