java学习笔记6(线程)
线程就是进程的儿子,没有了进程线程也( •̀ ω •́ )y就没有了,javascript没有线程的概念,但是有定时器(setTimeout),虽然没有java中名副其实的线程,但是也够用了;
java要使用线程有两种方式, 第一种是直接让类继承Thread, 第二种是让类继承Runnable接口的方式, 推荐使用继承接口(Runable)的方式使用线程;
第一种方式,使用extends继承Thread:
运行下面代码
public class ThreadDemo0 extends Thread{ private String name; public /*void*/ ThreadDemo0(String name) { this.name = name; }; public void run() { for(int i=0; i<10; i++) { System.out.println("THREAD: "+name+" run in thread " + i); }; }; public static void main (String args[]) { /* new ThreadDemo0("hehe").run(); new ThreadDemo0("lala").run(); */ new ThreadDemo0("hehe").start(); new ThreadDemo0("lala").start(); }; };
这种方式继承好理解, 要注意的是如果new出的线程 new ThreadDemo0("hehe") , start一次以后,再start一次是会报异常的,
所以我们每一次都要重新new这个类, 每一次都产生了新实例, 新实例跟上次实例化的实例一点关系都没有,我们无法简单地通过多线程同时做一件事情;
运行下面代码
public class ThreadDemo0 extends Thread{ private String name; private int arr[]; public /*void*/ ThreadDemo0(String name) { this.name = name; } public void setArr (int arr[]) { this.arr = arr; } public void run() { for(int i=0; i<this.arr[0]; i++) { System.out.println("THREAD: "+name+" run in thread " + i); }; }; public static void main (String args[]) { int sArr[] = {10}; ThreadDemo0 t0 = new ThreadDemo0("hehe"); ThreadDemo0 t1 = new ThreadDemo0("lala"); t1.setArr(sArr); t0.setArr(sArr); t1.start(); t0.start(); }; };
Runnable跟Thread有点不同, Runnable相当于你运行的代码在多个线程里面是共享的, 这个才是真正的多线程哇
运行下面代码
public class RunAndThread0 implements Runnable{ private int ticket = 5; public RunAndThread0( ) { } public void run() { while( true ) { if( ticket>0 ) { System.out.println("sell one; has tickets " + --ticket); }else{ return ; } } } public static void main(String []args) { RunAndThread0 run = new RunAndThread0(); //to use interface Runnable to share the variables; new Thread(run).start(); new Thread(run).start(); } }
Runnable是实现的Thread的run接口, 最后再通过Thread启动线程;
如果你不想共享作用域内的代码变量,你再重新实例化一个Runnable,重启一个线程, 这个效果跟extends Thread一样的:
运行下面代码
public class RunnableDemo0 implements Runnable { private String name; public RunnableDemo0(String name) { this.name = name; } public void run() { for(int i=0; i<10; i++) { System.out.println(name+" in thread " + i); } } public static void main(String[] args) { RunnableDemo0 hehe = new RunnableDemo0("hehe"); Thread tHehe = new Thread(hehe); RunnableDemo0 lala = new RunnableDemo0("lala"); Thread tLala = new Thread(lala); tHehe.start(); tLala.start(); } }
通过Thread.currentThread()可以获取当前的正在执行的线程, getName()可以获取线程的名字, 如果我们没有给线程起名字, 系统会为线程起名字,像这样的:
Thread-0, Thread-1, Thread-2, Thread-3....
运行下面代码
public class CurrentThread implements Runnable{ public void run( ) { System.out.println( Thread.currentThread().getName() ); } public static void main(String []args) { CurrentThread ct = new CurrentThread(); Thread tCt = new Thread(ct); tCt.start(); System.out.println(tCt.isAlive()); //this is main thread; new CurrentThread().run(); System.out.println(tCt.isAlive()); System.out.println(tCt.isAlive()); System.out.println(tCt.isAlive()); } }
Thread.sleep,就是让线程睡觉去, 参数是毫秒, (1000毫秒为1秒),Thread.sleep要用tryCatch包裹起来,要么编译的时候会有提示,你不加,他还编译不过去(太矫情了,这个是为什么呢?):
运行下面代码
public class ThreadSleep implements Runnable{ public void run() { try{ Thread.sleep(5000); }catch(Exception e) { e.printStackTrace(); } System.out.println("sleeping"); } public static void main(String []args) { new Thread( new ThreadSleep() ).start(); } }
线程的优先级Priority, 优先级越高的话, 线程越早开始跑,系统默认的优先级为5, 最低的为1, 最高的为10,通过setPriority设置到线程的实例:
运行下面代码
public class ThreadPriority implements Runnable { public void run( ) { for( int i=0 ;i < 10; i++) { System.out.println(Thread.currentThread().getName() + " : " + Thread.currentThread().getPriority()); }; } public static void main(String args[]) { new Thread(new ThreadPriority()).start(); Thread t0 = new Thread(new ThreadPriority()); t0.setPriority(10); t0.start(); Thread t1 = new Thread(new ThreadPriority()); t1.setPriority(1); t1.start(); } }
线程的join方法, 就是把一个线程加在另一个线程后面运行的(排队上车, 你先上好了,我等等, 我就跟你后面):
运行下面代码
public class ThreadJoin implements Runnable{ private Thread t; public ThreadJoin() {} public ThreadJoin( Thread t ) { this.t = t; } public void run() { for(int i=0 ; i<40; i++) { try{ if(i>10&&t.isAlive()) { t.join(); }; }catch( Exception e){ //e.printStackTrace(); } System.out.println( "thread name"+ Thread.currentThread().getName() + " i = " + i ); } } public static void main(String [] args) { Thread t0 = new Thread(new ThreadJoin()); t0.start(); Thread t1 = new Thread(new ThreadJoin(t0)); t1.start(); } }
如果一个线程同时操作一条数据,因为两个线程不是同步的,导致数据不同步, 就比如两个人抢银行, 一个人抢了30元, 一个人抢了40元,本来银行就只有40元钱, 银行跟两个盗窃者承诺了给钱 ,银行给了一个人40元, 又给了一个人30元, 发现自己亏了30元, 银行郁闷了:
运行下面代码
public class ThreadSync implements Runnable{ private int ticket = 10; public void run( ) { while(true) { if(ticket>0) { try{ //we should to do someting , to sure users state; Thread.sleep(1000); }catch( Exception e) { e.printStackTrace(); }; ticket--; System.out.println("lev :" + ticket); }else{ return; } } } public static void main(String [] args) { ThreadSync ts = new ThreadSync(); Thread t0 = new Thread(ts); Thread t1 = new Thread(ts); Thread t2 = new Thread(ts); Thread t3 = new Thread(ts); t0.start(); t1.start(); t2.start(); t3.start(); } }
卖出去的票出问题, 坑爹地变成了负数, 然道让多出来的乘客站着吗。。。。多线程的问题
如何解决这个问题呢,我们使用synchronized方法:
运行下面代码
public class Sync implements Runnable{ private int ticket = 10; public void run( ) { while(true) { synchronized( this ) { if(ticket>0) { try{ //we should to do someting , to sure users state; Thread.sleep(1000); }catch( Exception e) { e.printStackTrace(); }; ticket--; System.out.println("lev :" + ticket); }else{ return; } } } } public static void main(String [] args) { Sync ts = new Sync(); Thread t0 = new Thread(ts); Thread t1 = new Thread(ts); Thread t2 = new Thread(ts); Thread t3 = new Thread(ts); t0.start(); t1.start(); t2.start(); t3.start(); } }
或者使用synchronzed方法语句:
运行下面代码
public class SyncB implements Runnable{ private int ticket = 10; public void run( ) { while(true) { if( toRun() ) { return ; } } } public synchronized boolean toRun( ) { if(ticket>0) { try{ //we should to do someting , to sure users state; Thread.sleep(1000); }catch( Exception e) { e.printStackTrace(); }; ticket--; System.out.println("lev :" + ticket); return false; }else{ return true; } } public static void main(String [] args) { Sync ts = new Sync(); Thread t0 = new Thread(ts); Thread t1 = new Thread(ts); Thread t2 = new Thread(ts); Thread t3 = new Thread(ts); t0.start(); t1.start(); t2.start(); t3.start(); } }
运行后的效果跟上面一模一样,就可以避免线程同时访问导致数据不对头的问题;
本文作者:方方和圆圆
本文链接:https://www.cnblogs.com/diligenceday/p/4339946.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步