JAVA--浅谈线程
2016-04-21 16:28
731 查看
写在前面:
以下均为楼主自己理解,请多指正!
线程简介
现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。
线程是指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
“同时”执行是人的感觉,在线程之间实际上轮换执行。
线程的实现
1).通过继承Thread类实现线程
通过创建新的类继承Thread类,重写基类Thread中的run方法即可实现,在需要启动线程的地方,通过Thread中的Start()方法即可实现线程的启动。
代码实例:
2).通过实现Runnable接口实现线程
通过Thread thread = new Thread(new Runnable(){});来实现,Runnable接口内包含run()方法,只需在接口内实现该方法并启动即可实现线程。
代码实例:
线程的休眠
以下是线程的生命周期示意图,线程包含 出生、就绪、运行、等待、休眠、阻塞、死亡状态。其中线程的休眠使用sleep()方法是实现。使用了sleep()的线程会在一段时间后醒来,但是并不能保证线程醒来后即可进入运行状态,只能进入就绪状态。
代码实例:
线程的加入
线程的加入顾名思义即为将一个线程加入到当前的线程,当前线程会在加入的线程运行完后继续执行,线程的加入使用join()方法,代码实例:
线程的优先级
1).与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。
2).线程的优先级用1-10之间的整数表示,数值越大优先级越高,默认的优先级为5。
3).在一个线程中开启另外一个新线程,则新开线程称为该线程的子线程,子线程初始优先级与父线程相同。
4).使用setPriority(int newPriority)方法设置线程的优先级,备选的有三个定义常量Thread.MAX_PRIORITY = 10 、Thread.MIN_PRIORITY = 1、Thread.NORM_PRIORITY= 5,自定义线程优先级的时候范围为1-10的整数。
- 线程的同步
为什么会产生线程的同步的想法?
在多个进程访问公共资源的时候,将会产生bug,示例如下:
运行结果:
在上述线程中,某一线程将票售出,第二个线程也已经完成了判断余票的工作,于是将不存在的票继续出售,产生了线程安全问题,因此继续解决多线程之间对公共资源的访问问题。
线程的同步是利用临界资源的思想来解决问题,当多个线程需要访问一些公有资源的时候,将公有资源上锁,只允许一个进程进行访问。即可解决线程安全问题。使用synchronized(Object){// 公共资源的访问},当其他线程获取到这个锁的时候,必须等待锁被释放才能够进入该区域。Object为任意对象,每个对象都存在一个标志位,并具有0、1两个值,而这个值即为同步锁,线程运行到此处,会首先检查该对象的标志位,如果为0,即表示此同步块在其他线程中运行,此时线程处于就绪状态,反之,进入运行,并修改标志位。
修改上述代码:
运行结果:
以下均为楼主自己理解,请多指正!
线程简介
现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。
线程是指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
“同时”执行是人的感觉,在线程之间实际上轮换执行。
线程的实现
1).通过继承Thread类实现线程
通过创建新的类继承Thread类,重写基类Thread中的run方法即可实现,在需要启动线程的地方,通过Thread中的Start()方法即可实现线程的启动。
代码实例:
/** * */ package test线程; /** * @author 寒 * */ public class TestThread extends Thread{ private String name; /** * @param string */ public TestThread(String string) { // TODO 自动生成的构造函数存根 this.name = string; } public void run(){ for(int i = 0; i < 10 ; i++){ System.out.println("第" + i + "次调用" + this.name + " " + this.getName()); } } /** * @param args */ public static void main(String[] args) { // TODO 自动生成的方法存根 new TestThread(" 我是线程0 ").start(); new TestThread(" 我是线程1 ").start(); } }
2).通过实现Runnable接口实现线程
通过Thread thread = new Thread(new Runnable(){});来实现,Runnable接口内包含run()方法,只需在接口内实现该方法并启动即可实现线程。
代码实例:
/** * */ package test线程; import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JProgressBar; /** * @author 寒 * */ public class InterruptedSwing extends JFrame{ Thread thread; /** * @param args */ public static void main(String[] args) { // TODO 自动生成的方法存根 init(new InterruptedSwing(), 300,300); } public InterruptedSwing(){ super(); final JProgressBar progressBar = new JProgressBar(); getContentPane().add(progressBar, BorderLayout.NORTH); progressBar.setStringPainted(true); thread = new Thread(new Runnable(){ int count = 0; @Override public void run() { // TODO 自动生成的方法存根 while(true){ progressBar.setValue( ++ count); try{ Thread.sleep(1000); }catch(InterruptedException e){ e.printStackTrace(); } } } }); thread.start(); thread.interrupt(); } public static void init(JFrame frame, int width , int height){ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(width, height); frame.setVisible(true); } }
线程的休眠
以下是线程的生命周期示意图,线程包含 出生、就绪、运行、等待、休眠、阻塞、死亡状态。其中线程的休眠使用sleep()方法是实现。使用了sleep()的线程会在一段时间后醒来,但是并不能保证线程醒来后即可进入运行状态,只能进入就绪状态。
代码实例:
/** * */ package test线程; import java.awt.Color; import java.awt.Graphics; import java.util.Random; import javax.swing.*; /** * @author 寒 * */ public class SleepMethodTest extends JFrame{ private Thread t; private static Color []color = {Color.BLACK,Color.BLUE, Color.CYAN,Color.GREEN, Color.ORANGE,Color.PINK,Color.YELLOW,Color.WHITE}; private static final Random rand = new Random(); private static Color getC(){ return color[rand.nextInt(color.length)]; } public SleepMethodTest(){ t = new Thread(new Runnable(){ int x = 30; int y =50; @Override public void run() { // TODO 自动生成的方法存根 while(true){ try{ Thread.sleep(100); }catch(InterruptedException e){ e.printStackTrace(); } Graphics graphics = getGraphics(); graphics.setColor(getC()); graphics.drawLine(x, y, 100, y++); if (y > 80){ y = 50 ; } } } }); t.start(); } /** * @param args */ public static void main(String[] args) { // TODO 自动生成的方法存根 init(new SleepMethodTest(),100 ,100 ); } public static void init(JFrame jframe , int width , int height){ jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jframe.setSize(width, height); jframe.setVisible(true); } }
线程的加入
线程的加入顾名思义即为将一个线程加入到当前的线程,当前线程会在加入的线程运行完后继续执行,线程的加入使用join()方法,代码实例:
/** * */ package test线程; import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JProgressBar; /** - @author 寒 - */ public class JoinTest extends JFrame { private Thread threadA; private Thread threadB; final JProgressBar progressBar = new JProgressBar(); final JProgressBar progressBar2 = new JProgressBar(); int count = 0; /** * @param args */ public static void main(String[] args) { // TODO 自动生成的方法存根 init(new JoinTest(), 300, 300); } public JoinTest() { super(); getContentPane().add(progressBar, BorderLayout.NORTH); getContentPane().add(progressBar2, BorderLayout.SOUTH); progressBar.setStringPainted(true); progressBar2.setStringPainted(true); threadA = new Thread(new Runnable() { int count = 0; @Override public void run() { // TODO 自动生成的方法存根 while (true) { progressBar.setValue(++count); try { Thread.sleep(100); threadB.join();//先执行线程B } catch (Exception e) { e.printStackTrace(); } } } }); threadA.start(); threadB = new Thread(new Runnable() { int count = 0; @Override public void run() { // TODO 自动生成的方法存根 while (true) { progressBar2.setValue(++count); try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } if (count == 100) { break; } } } }); threadB.start(); } public static void init(JFrame frame, int width, int height) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(width, height); frame.setVisible(true); } }
线程的优先级
1).与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。
2).线程的优先级用1-10之间的整数表示,数值越大优先级越高,默认的优先级为5。
3).在一个线程中开启另外一个新线程,则新开线程称为该线程的子线程,子线程初始优先级与父线程相同。
4).使用setPriority(int newPriority)方法设置线程的优先级,备选的有三个定义常量Thread.MAX_PRIORITY = 10 、Thread.MIN_PRIORITY = 1、Thread.NORM_PRIORITY= 5,自定义线程优先级的时候范围为1-10的整数。
- 线程的同步
为什么会产生线程的同步的想法?
在多个进程访问公共资源的时候,将会产生bug,示例如下:
package test线程; public class ThreadSafeTest implements Runnable { int num = 10; public static void main(String[] args) { // TODO 自动生成的方法存根 ThreadSafeTest test = new ThreadSafeTest(); Thread thread_a = new Thread(test); Thread thread_b = new Thread(test); Thread thread_c = new Thread(test); Thread thread_d = new Thread(test); thread_a.start(); thread_b.start(); thread_c.start(); thread_d.start(); } @Override public void run() { // TODO 自动生成的方法存根 while (true) { if (num > 0) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } System.out.println( "tickets :" + num--); } else{ break; } } } }
运行结果:
tickets :10 tickets :9 tickets :8 tickets :7 tickets :6 tickets :5 tickets :5 tickets :5 tickets :4 tickets :3 tickets :2 tickets :1 tickets :0 tickets :-1 tickets :-2
在上述线程中,某一线程将票售出,第二个线程也已经完成了判断余票的工作,于是将不存在的票继续出售,产生了线程安全问题,因此继续解决多线程之间对公共资源的访问问题。
线程的同步是利用临界资源的思想来解决问题,当多个线程需要访问一些公有资源的时候,将公有资源上锁,只允许一个进程进行访问。即可解决线程安全问题。使用synchronized(Object){// 公共资源的访问},当其他线程获取到这个锁的时候,必须等待锁被释放才能够进入该区域。Object为任意对象,每个对象都存在一个标志位,并具有0、1两个值,而这个值即为同步锁,线程运行到此处,会首先检查该对象的标志位,如果为0,即表示此同步块在其他线程中运行,此时线程处于就绪状态,反之,进入运行,并修改标志位。
修改上述代码:
@Override public void run() { // TODO 自动生成的方法存根 while (true) { synchronized ("") { if (num > 0) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } System.out.println( "tickets :" + num--); } else{ break; } } } }
运行结果:
tickets :10 tickets :9 tickets :8 tickets :7 tickets :6 tickets :5 tickets :4 tickets :3 tickets :2 tickets :1
相关文章推荐
- [改善Java代码]易变业务使用脚本语言编写
- java IO 一 (读写字符串)
- JAVA守护线程
- spring整合消息队列rabbitmq
- JavaMail类
- Java类代码块执行顺序
- java要注意的问题1
- Java反射机制Class类的用法详解
- SpringMvc、Maven整合FreeMarker--访问不到js、css
- JAVA中Action层, Service层 ,modle层 和 Dao层的功能区分
- 启动报错: org.springframework.web.context.ContextLoaderListener
- Spring容器启动后注入service到Servlet并自动执行
- Java 泛型的限定
- 关于javax包找不到
- [改善Java代码]慎用动态编译
- [spring源码学习]五-BeanPostProcessor的使用
- java反射详解
- Spring学习——Aop原理
- java多线程编程的volatile应用
- JDK之jstat的用法