进程和多线程的概念以及线程的优点
1.进程概念
2.线程概念
3.优点
使用多线程
接触下线程
public class Demo1 { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()); } }
1.继承Thread类
代码运行和代码执行和调用顺序无关
自定义一个线程类:
public class MyThread extends Thread{ @Override public void run() { super.run(); System.out.println("Mythead"); } public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); System.out.println("运行结束!"); } }
线程调用的随机性
public class RandomThread 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("run==" + Thread.currentThread().getName()); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { try { RandomThread randomThread = new RandomThread(); randomThread.setName("myThread"); randomThread.start(); for (int i = 0; i < 10; i++) { int time = (int) (Math.random() * 1000); Thread.sleep(time); System.out.println("run==" + Thread.currentThread().getName()); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("run==" + Thread.currentThread().getName()); } }
执行start方法的顺序不代表线程启动顺序
public class ThreadDemo extends Thread{ private int i; public ThreadDemo(int i){ super(); this.i = i; } @Override public void run() { System.out.println(i); } public static void main(String[] args) { ThreadDemo t1 = new ThreadDemo(1); ThreadDemo t2 = new ThreadDemo(2); ThreadDemo t3 = new ThreadDemo(3); ThreadDemo t4 = new ThreadDemo(4); ThreadDemo t5 = new ThreadDemo(5); ThreadDemo t6 = new ThreadDemo(6); ThreadDemo t7 = new ThreadDemo(7); ThreadDemo t8 = new ThreadDemo(8); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start(); t7.start(); t8.start(); } }
2.实现Runnable接口
如何使用Runable类呢?
public class Run { public static void main(String[] args) { MyRunable myRunable = new MyRunable(); Thread thread = new Thread(myRunable); thread.start(); System.out.println("运行结束"); } }
3.实例变量与线程安全
(1)不共享数据的情况
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("由 " + 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(); } }
(2)共享数据的情况
线程安全问题案例1
测试项目
public class MyThread extends Thread{ private int count=5; @Override 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 MyThread extends Thread { private int count = 5; @Override synchronized public void run() { count--; System.out.println("由 " + this.currentThread().getName() + " 计算,count=" + count); } }
线程安全问题2
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="+passwordRef); }catch (InterruptedException 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
synchronized public static void doPost(String username, String password){
留意i–和system.out.println()异常
案例演示
public class MyThread extends Thread { private int i = 5; @Override public void run() { System.out.println("i=" + (i--)+ " threadName=" + Thread.currentThread().getName()); //注意: 代码i--由前面项目中单独一行运行改成在当前项目中在println()方法中直接进行打印 } public static void main(String[] args) { MyThread run = new MyThread(); Thread t1 = new Thread(run); Thread t2 = new Thread(run); Thread t3 = new Thread(run); Thread t4 = new Thread(run); Thread t5 = new Thread(run); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } }
为了防止发生非线程安全问题,还是应该继续使用同步方法。
4.currentThread()方法
该方法返回代码段正在被哪个线程调用的信息。
1.案例1
public class MyThread extends Thread{ public MyThread() { System.out.println("构造方法的打印: "+ Thread.currentThread().getName()); } @Override public void run() { System.out.println("run构造方法的打印: "+ Thread.currentThread().getName()); } public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); } }
改下:
public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.run(); }
均被main主线程所调用。
2.案例2:
public class CountOperate extends Thread{ public CountOperate() { System.out.println("countOpera---begin"); System.out.println("Thread.currentThread.getName()=" + Thread.currentThread().getName()); System.out.println("this.getName()==" + this.getName()); System.out.println("countOpera---end"); } @Override public void run() { System.out.println("countOpera---begin"); System.out.println("Thread.currentThread.getName()=" + Thread.currentThread().getName()); System.out.println("this.getName()==" + this.getName()); System.out.println("countOpera---end"); } public static void main(String[] args) { CountOperate c = new CountOperate(); Thread t1 = new Thread(c); t1.setName("A"); t1.start(); } }
5.isAlive()方法
判断当前的线程是否是活跃的状态
public class MyThread extends Thread { @Override public void run() { System.out.println("begin==" + this.isAlive()); } public static void main(String[] args) { MyThread myThread = new MyThread(); System.out.println("begin==" + myThread.isAlive()); myThread.start(); System.out.println("end==" + myThread.isAlive()); } }
public static void main(String[] args) throws InterruptedException { MyThread myThread = new MyThread(); System.out.println("begin==" + myThread.isAlive()); myThread.start(); Thread.sleep(1000); System.out.println("end==" + myThread.isAlive()); }
6.sleep()方法
public class MyThread extends Thread { @Override public void run() { try { System.out.println("run threadName="+this.currentThread().getName() + " begin"); Thread.sleep(2000); System.out.println("run threadName="+this.currentThread().getName() + " end"); }catch (Exception e){ e.printStackTrace(); } } public static void main(String[] args) { MyThread myThread = new MyThread(); System.out.println("begin = " + System.currentTimeMillis()); myThread.start(); System.out.println("end = " + System.currentTimeMillis()); } }
修改实验
public static void main(String[] args) { MyThread myThread = new MyThread(); System.out.println("begin = " + System.currentTimeMillis()); myThread.run(); System.out.println("end = " + System.currentTimeMillis()); }
6.getId()方法
public static void main(String[] args) { Thread thread = Thread.currentThread(); System.out.println(thread.getId() + "====" + thread.getName()); }
当前线程的id为1,名字为main。