Java程序的运行原理:
由Java命令启动JVM,JVM启动就相当于启动了一个进程,接着由该进程创建了一个主线程去调用main方法
jvm虚拟机的启动是单线程的还是多线程的?
多线程的;原因是垃圾回收线程也要先启动,否则很容易出现内存溢出;现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,jvm的启动其实是多线程的
并行和并发 前者是逻辑上同时发生,指在某一个时间内同时运行多个程序; 后者是物理上同时发生,指在某一个时间点同时运行多个程序
public class MyThread extends Thread { @Override public void run() { for (int x = 0; x < 500; x++) { System.out.println(getName() + " " + x); } } }
public class MyThreadDemo { public static void main(String[] args) { //创建线程对象 //调用run()方法为什么是单线程呢? //因为run()方法直接调用其实就相当于普通的方法调用,所以你看到的是单线程的效果 //面试题:run()和start()的区别? //run():仅仅是封装被线程执行的代码,直接调用是普通方法 //start():首先启动了线程,然后再由jvm去调用该线程的run()方法 MyThread mt=new MyThread(); mt.start(); //IllegalThreadStateException:非法的线程状态异常 //为什么呢?因为这个相当于mt线程被调用了两次,而不是启动了两个线程 // mt.start(); MyThread m1=new MyThread(); MyThread m2=new MyThread(); m1.start(); m2.start(); } }
//我要获取main方法所在的线程对象的名称,该怎么办? //public static Thread currentThread()返回对当前正在执行的线程对象的引用。 Thread.currentThread().getName();

注意:
线程默认优先级是5
线程优先级的范围是:1-10
线程优先级高仅仅表示线程获取的CPU时间片的几率高,但是要在次数比较多,
或者多次运行的时候才能看到比较好的效果

public class ThreadJoin extends Thread{ @Override public void run() { for (int x=0;x<1000;x++){ System.out.println(getName()+": "+x); } } }
public static void main(String[] args) { ThreadJoin tj1=new ThreadJoin(); ThreadJoin tj2=new ThreadJoin(); ThreadJoin tj3=new ThreadJoin(); tj1.setName("李渊"); tj2.setName("李世民"); tj3.setName("李治"); tj1.start(); try { // 该线程执行完, 其他线程才能开始抢占 tj1.join(); } catch (InterruptedException e) { e.printStackTrace(); } tj2.start(); tj3.start(); }

礼让
public static void yield()暂停当前正在执行的线程对象,并执行其他线程。 让多个线程的执行更和谐,但不能靠它保证一人一次
public class ThreadYield extends Thread { @Override public void run() { for (int x=0;x<100;x++){ System.out.println(getName()+": "+x); ThreadYield.yield(); } } }
public static void main(String[] args) { ThreadYield ty1=new ThreadYield(); ThreadYield ty2=new ThreadYield(); ty1.setName("西施"); ty2.setName("萧太后"); ty1.start(); ty2.start(); }


/** * public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程。 * 当正在运行的线程都是守护线程时,Java 虚拟机退出. 该方法必须在启动线程前调用。 * * 游戏: 坦克大战 * */
public class ThreadDaemon extends Thread{ @Override public void run() { for (int x=0;x<100;x++){ System.out.println(getName()+": "+x); } } }
public static void main(String[] args) { ThreadDaemon td1 = new ThreadDaemon(); ThreadDaemon ts2 = new ThreadDaemon(); td1.setName("关羽"); ts2.setName("张飞"); //设置收获线程 td1.setDaemon(true); ts2.setDaemon(true); td1.start(); ts2.start(); Thread.currentThread().setName("刘备"); for (int x = 0; x < 5; x++) { System.out.println(Thread.currentThread().getName() + ": " + x); } }


public class MyRunnable implements Runnable { @Override public void run() { for (int x=0;x<100;x++){ //由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用 System.out.println(Thread.currentThread().getName()+": "+x); } } }
public static void main(String[] args) { //创建Runnable类的对象 MyRunnable mr=new MyRunnable(); //public Thread(Runnable target,tring name) Thread t1=new Thread(mr,"666"); Thread t2=ew Thread(mr,"121"); t1.start(); t2.start(); }
如何解决线程安全问题呢? 要想解决问题,就要知道哪些原因会导致出问题: A:是否是多线程环境 B:是否是共享数据 C:是否有多条语句操作共享数据
同步代码块:
synchronized(对象){
需要同步的代码;
}
注意:
同步可以解决安全问题的根本原因就是在那个对象上,该对象如同锁的功能
多个线程必须是同一把锁
/** * 举例: * 火车上上厕所 * 同步的特点: * 前提: 多个线程 * 解决问题的时候要注意:多个线程使用的是同一锁对象 * 同步的好处 * 同步的出现解决了多线程的安全问题 * 同步的弊端 * 当线程相当多时,因为每个线程都回去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率 * * */ /* * A:同步代码块的锁对象是谁呢? 任意对象 * B:同步方法的格式及锁对象问题? 把同步关键字加在方法上 * 同步方法是谁呢? this * c:静态方法及锁对象问题? * 静态方法的锁对象是谁呢? * 类的字节码文件对象。 * */
public class SellTicket implements Runnable { //定义100张票 private int tickets=100; //创建锁对象 private Object object=new Object(); @Override public void run() { while (true){ synchronized (object){ if (tickets>0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"张票"); } } } } }
public class SellTicket implements Runnable{ //定义100张票 private int tickets=100; private int x=0; @Override public void run() { while (true) { if (x%2==0) { synchronized (this) { if (tickets > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } } else { sellTicket(); } x++; } } private synchronized void sellTicket() { if(tickets > 0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } }
public class SellTicket implements Runnable{ //定义100张票 private static int tickets=100; private int x=0; @Override public void run() { while (true) { if (x%2==0) { synchronized (SellTicket.class) { if (tickets > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } } else { sellTicket(); } x++; } } private static synchronized void sellTicket() { if(tickets > 0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } }
来源:oschina
链接:https://my.oschina.net/u/2954646/blog/3186889