进程VS线程VS多线程
多线程编程
-
继承Thread类
-
实现Runnable接口
继承Thread类
// mythread.java
public class Mythread extends Thread{
@Override
public void run(){
System.out.println("My thread");
}
}
// run.java
public class Run {
public static void main(String[] args) {
Mythread mythread = new Mythread();
mythread.start();
System.out.println("End");
}
}
代码运行结果与代码的执行顺序或调用顺序无关(线程的随机性)
线程随机性
// mythread.java
public class Mythread extends Thread{
@Override
public void run(){
try {
for (int i = 0; i < 10; i++){
int time = (int) (Math.random()*1000);
Thread.sleep(time);
System.out.println("Mythread run=" + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// run.java
public class Run {
public static void main(String[] args) {
Mythread mythread = new Mythread();
mythread.setName("Mythread");
mythread.start();
try {
for (int i = 0; i < 10; i++){
int time = (int) (Math.random()*1000);
Thread.sleep(time);
System.out.println("Main run=" + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
此处myThread.start()替换为myThread.run()的区别在于start()和main的线程为异步,换成run()后为同步,需要等到main的线程来调用,即等run()方法中的代码执行完后才可以执行后面的代码。
执行start()方法的顺序不代表线程启动的顺序,代码如下:
// mythread.java
public class Mythread extends Thread{
private int i;
public Mythread(int i) {
super();
this.i = i;
}
@Override
public void run(){
System.out.println(i);
}
}
// run.java
public class Run {
public static void main(String[] args) {
Mythread mt1 = new Mythread(1);
Mythread mt2 = new Mythread(2);
Mythread mt3 = new Mythread(3);
Mythread mt4 = new Mythread(4);
Mythread mt5 = new Mythread(5);
Mythread mt6 = new Mythread(6);
Mythread mt7 = new Mythread(7);
Mythread mt8 = new Mythread(8);
Mythread mt9 = new Mythread(9);
Mythread mt10 = new Mythread(10);
mt1.start();
mt2.start();
mt3.start();
mt4.start();
mt5.start();
mt6.start();
mt7.start();
mt8.start();
mt9.start();
mt10.start();
}
}
实现Runnable接口
// myRunnable.java
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("Run");
}
}
// run.java
public class Run {
public static void main(String[] args) {
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
System.out.println("Run end");
}
}
实例变量与线程安全
线程不同享
多个线程分别处理自己对应的count
// mythread.java
public class Mythread extends Thread{
private int count = 5;
public Mythread(String name) {
super();
this.setName(name);
}
@Override
public void run(){
super.run();
while (count > 0){
count--;
System.out.println(" 由 " + currentThread().getName() + " 计算, count=" + count);
}
}
}
// run.java
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();
}
}
运行结果:
由 A 计算, count=4
由 B 计算, count=4
由 C 计算, count=4
由 B 计算, count=3
由 B 计算, count=2
由 B 计算, count=1
由 B 计算, count=0
由 A 计算, count=3
由 C 计算, count=3
由 C 计算, count=2
由 C 计算, count=1
由 C 计算, count=0
由 A 计算, count=2
由 A 计算, count=1
由 A 计算, count=0
线程共享
多个线程共同处理一个count
// mythread.java
public class Mythread extends Thread{
private int count = 5;
@Override
public void run(){
super.run();
count--;
System.out.println(" 由 " + currentThread().getName() + " 计算, count=" + count);
}
}
// run.java
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();
}
}
运行结果:
由 A 计算, count=3
由 E 计算, count=1
由 C 计算, count=2
由 B 计算, count=3
由 D 计算, count=0
结果产生非线程安全问题。
某些JVM中,i–操作为3步:
-
取原有i值。
-
计算i-1。
-
对i进行赋值。
加synchronized改为线程安全:
// mythread.java
public class Mythread extends Thread{
private int count = 5;
@Override
synchronized public void run(){
super.run();
count--;
System.out.println(" 由 " + currentThread().getName() + " 计算, count=" + count);
}
}
// run.java
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();
}
}
运行结果:
由 A 计算, count=4
由 C 计算, count=3
由 E 计算, count=2
由 D 计算, count=1
由 B 计算, count=0
另一个非线程安全的例子,解决方法加synchronized关键字
// loginServlet.java 模拟servlet组件
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 (InterruptedException e){
e.printStackTrace();
}
}
}
// alogin.java
public class ALogin extends Thread{
@Override
public void run(){
LoginServlet.doPost("a","aa");
}
}
// blogin.java
public class BLogin extends Thread{
@Override
public void run(){
LoginServlet.doPost("b","bb");
}
}
// run.java
public class Run {
public static void main(String[] args) {
ALogin a = new ALogin();
a.start();
BLogin b = new BLogin();
b.start();
}
}
运行结果:
username=b password=bb
username=b password=aa
加synchronized关键字后:
synchronized 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 (InterruptedException e){
e.printStackTrace();
}
}
运行结果:
username=a password=aa
username=b password=bb