关于java线程的一些东西
2016-09-28 11:21
453 查看
一、先简单描叙一下创建线程的方式通过继承Thread:
(1)定义一个类继承Thread类
(2)覆盖Thread类中的run方法
(3)直接创建Thread的子类对象线程
(4)调用start方法开启线程并调用线程的任务run方法执行
[java] view
plain copy
print?
public class ThreadDemo extends Thread {
private String name;
public ThreadDemo(String name){
this.name = name;
}
public void run(){
for(int i = 0; i < 9; i++){
System.out.println(name+"..........i="+i);
}
}
public static void main(String[] args) {
ThreadDemo demo = new ThreadDemo("李四");
ThreadDemo demo1 = new ThreadDemo("张三");
demo.start();
demo1.start();
}
}
二、run方法和start方法的区别
1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码:
通过调用Thread类的start()方法来启动一个线程,
这时此线程是处于就绪状态,
并没有运行。
然后通过此Thread类调用方法run()来完成其运行操作的,
这里方法run()称为线程体,
它包含了要执行的这个线程的内容,
Run方法运行结束,
此线程终止,
而CPU再运行其它线程,
2.run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码:
而如果直接用Run方法,
这只是调用一个方法而已,
程序中依然只有主线程--这一个线程,
其程序执行路径还是只有一条,
这样就没有达到写线程的目的。
举例说明一下:
记住:线程就是为了更好地利用CPU,
提高程序运行速率的!
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。
描述实现Runnable接口
(一)创建一个类,实现Runnable接口
(二)复写Runnable里面的run方法
(三)实例化这个类,调用start方法,此时线程开启,就执行该线程的run方法
[java] view
plain copy
print?
class MyThread implements Runnable{
private int ticket = 5; //5张票
public void run() {
for (int i=0; i<=20; i++) {
if (this.ticket > 0) {
System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
}
}
}
}
public class lzwCode {
public static void main(String [] args) {
MyThread my = new MyThread();
new Thread(my, "1号窗口").start();
new Thread(my, "2号窗口").start();
new Thread(my, "3号窗口").start();
}
}
实现Runnable接口的好处如下:
1.避免了java里面的单继承问题
2.适合多个相同的程序代码的线程去处理同一个资源
3.增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
一、产生线程安全的原因
(1)多个线程在操作共享数据
(2)操作共享数据的线程代码有多条
结论:当一个线程在执行操作共享数据的多条代码过程中,其他线程参与运算,就会导致线程安全问题的产生。
二、解决方案:同步锁,同步锁分为两种如下:
(1)同步锁代码块
[java] view
plain copy
print?
Synchronized(对象){
//code;
}
(2)同歩锁函数
[java] view
plain copy
print?
public synchronized void show(){
//code;
}
同步锁函数和同步代码块的区别:
①同步函数的锁是固定的this;
②同步代码块的锁是任意的对象;
③静态的同步函数使用的锁是该函数所属字节码文件对象,可以用getClass()方法获取,也可以用当前类名.class获取;
(3)使用同歩锁的前提:必须有多个线程并同时使用同一个锁;
三、死锁原因
(1)同步锁嵌套
[java] view
plain copy
print?
synchronized(MyLocked.locka){
System.out.println(Thread.currentThread().getName()+" if locka....");
synchronized(MyLocked.lockb){
System.out.println(Thread.currentThread().getName()+" if lockb....");
}
}
(2)线程间的通讯,多个线程在处理同一个资源,但任务却不同
[java] view
plain copy
print?
//资源
class Resource
{
String name;
String sex;
}
//输入
class Input implements Runnable
{
Resource r ;
// Object obj = new Object();
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(x==0)
{
r.name = "mike";
r.sex = "nan";
}
else
{
r.name = "丽丽";
r.sex = "女女女女女女";
}
}
x = (x+1)%2;
}
}
}
//输出
class Output implements Runnable
{
Resource r;
// Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
System.out.println(r.name+"....."+r.sex);
}
}
}
}
class ResourceDemo
{
public static void main(String[] args)
{
//创建资源。
Resource r = new Resource();
//创建任务。
Input in = new Input(r);
Output out = new Output(r);
//创建线程,执行路径。
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
//开启线程
t1.start();
t2.start();
}
}
四、等待/唤醒机制
(1)wait();让线程处于冻结状态,被wait的线程会被存储到线程池中;
(2)notify();唤醒线程池中一个线程(任意);
(3)notifyAll();唤醒线程池中的所有线程;
总结:这些方法都必须能定义在同步锁中,因为这些方法是用于操作线程状态的方法,必须能要明确到底操作的是哪个锁上的线程
为什么操作线程的方法wait notify notifyAll定义在了Object类中?
因为这些方法是监视器的方法。监视器其实就是锁。锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。
五、示例如下:
资源类:
[java] view
plain copy
print?
<span style="font-size:14px;">package com.edu.csu.syn;
public class Resource {
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name,String sex){
if(flag)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
public synchronized void out(){
if(!flag)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"......"+sex);
flag = false;
this.notify();
}
}
</span>
输入类:
[java] view
plain copy
print?
<span style="font-size:14px;">package com.edu.csu.syn;
public class Input implements Runnable {
private Resource r;
public Input(Resource r){
this.r = r;
}
@Override
public void run() {
int x = 0;
while(true){
if (x == 0) {
r.set("mike", "nan");
} else {
r.set("丽丽", "女女女女");
}
x = (x + 1) % 2;
}
}
}</span>
输出类:
[java] view
plain copy
print?
<span style="font-size:14px;">package com.edu.csu.syn;
public class Output implements Runnable {
private Resource r;
public Output(Resource r){
this.r = r;
}
@Override
public void run() {
while(true){
r.out();
}
}
}</span>
测试类:
[java] view
plain copy
print?
<span style="font-size:14px;">package com.edu.csu.syn;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
//创建资源
Resource r = new Resource();
//创建任务
Input i = new Input(r);
Output o = new Output(r);
//创建线程,执行任务
Thread t = new Thread(i);
Thread t1 = new Thread(o);
//开启线程
t.start();
t1.start();
}
}
</span>
(1)定义一个类继承Thread类
(2)覆盖Thread类中的run方法
(3)直接创建Thread的子类对象线程
(4)调用start方法开启线程并调用线程的任务run方法执行
[java] view
plain copy
print?
public class ThreadDemo extends Thread {
private String name;
public ThreadDemo(String name){
this.name = name;
}
public void run(){
for(int i = 0; i < 9; i++){
System.out.println(name+"..........i="+i);
}
}
public static void main(String[] args) {
ThreadDemo demo = new ThreadDemo("李四");
ThreadDemo demo1 = new ThreadDemo("张三");
demo.start();
demo1.start();
}
}
二、run方法和start方法的区别
1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码:
通过调用Thread类的start()方法来启动一个线程,
这时此线程是处于就绪状态,
并没有运行。
然后通过此Thread类调用方法run()来完成其运行操作的,
这里方法run()称为线程体,
它包含了要执行的这个线程的内容,
Run方法运行结束,
此线程终止,
而CPU再运行其它线程,
2.run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码:
而如果直接用Run方法,
这只是调用一个方法而已,
程序中依然只有主线程--这一个线程,
其程序执行路径还是只有一条,
这样就没有达到写线程的目的。
举例说明一下:
记住:线程就是为了更好地利用CPU,
提高程序运行速率的!
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。
描述实现Runnable接口
(一)创建一个类,实现Runnable接口
(二)复写Runnable里面的run方法
(三)实例化这个类,调用start方法,此时线程开启,就执行该线程的run方法
[java] view
plain copy
print?
class MyThread implements Runnable{
private int ticket = 5; //5张票
public void run() {
for (int i=0; i<=20; i++) {
if (this.ticket > 0) {
System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
}
}
}
}
public class lzwCode {
public static void main(String [] args) {
MyThread my = new MyThread();
new Thread(my, "1号窗口").start();
new Thread(my, "2号窗口").start();
new Thread(my, "3号窗口").start();
}
}
实现Runnable接口的好处如下:
1.避免了java里面的单继承问题
2.适合多个相同的程序代码的线程去处理同一个资源
3.增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
一、产生线程安全的原因
(1)多个线程在操作共享数据
(2)操作共享数据的线程代码有多条
结论:当一个线程在执行操作共享数据的多条代码过程中,其他线程参与运算,就会导致线程安全问题的产生。
二、解决方案:同步锁,同步锁分为两种如下:
(1)同步锁代码块
[java] view
plain copy
print?
Synchronized(对象){
//code;
}
(2)同歩锁函数
[java] view
plain copy
print?
public synchronized void show(){
//code;
}
同步锁函数和同步代码块的区别:
①同步函数的锁是固定的this;
②同步代码块的锁是任意的对象;
③静态的同步函数使用的锁是该函数所属字节码文件对象,可以用getClass()方法获取,也可以用当前类名.class获取;
(3)使用同歩锁的前提:必须有多个线程并同时使用同一个锁;
三、死锁原因
(1)同步锁嵌套
[java] view
plain copy
print?
synchronized(MyLocked.locka){
System.out.println(Thread.currentThread().getName()+" if locka....");
synchronized(MyLocked.lockb){
System.out.println(Thread.currentThread().getName()+" if lockb....");
}
}
(2)线程间的通讯,多个线程在处理同一个资源,但任务却不同
[java] view
plain copy
print?
//资源
class Resource
{
String name;
String sex;
}
//输入
class Input implements Runnable
{
Resource r ;
// Object obj = new Object();
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(x==0)
{
r.name = "mike";
r.sex = "nan";
}
else
{
r.name = "丽丽";
r.sex = "女女女女女女";
}
}
x = (x+1)%2;
}
}
}
//输出
class Output implements Runnable
{
Resource r;
// Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
System.out.println(r.name+"....."+r.sex);
}
}
}
}
class ResourceDemo
{
public static void main(String[] args)
{
//创建资源。
Resource r = new Resource();
//创建任务。
Input in = new Input(r);
Output out = new Output(r);
//创建线程,执行路径。
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
//开启线程
t1.start();
t2.start();
}
}
四、等待/唤醒机制
(1)wait();让线程处于冻结状态,被wait的线程会被存储到线程池中;
(2)notify();唤醒线程池中一个线程(任意);
(3)notifyAll();唤醒线程池中的所有线程;
总结:这些方法都必须能定义在同步锁中,因为这些方法是用于操作线程状态的方法,必须能要明确到底操作的是哪个锁上的线程
为什么操作线程的方法wait notify notifyAll定义在了Object类中?
因为这些方法是监视器的方法。监视器其实就是锁。锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。
五、示例如下:
资源类:
[java] view
plain copy
print?
<span style="font-size:14px;">package com.edu.csu.syn;
public class Resource {
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name,String sex){
if(flag)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
public synchronized void out(){
if(!flag)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"......"+sex);
flag = false;
this.notify();
}
}
</span>
输入类:
[java] view
plain copy
print?
<span style="font-size:14px;">package com.edu.csu.syn;
public class Input implements Runnable {
private Resource r;
public Input(Resource r){
this.r = r;
}
@Override
public void run() {
int x = 0;
while(true){
if (x == 0) {
r.set("mike", "nan");
} else {
r.set("丽丽", "女女女女");
}
x = (x + 1) % 2;
}
}
}</span>
输出类:
[java] view
plain copy
print?
<span style="font-size:14px;">package com.edu.csu.syn;
public class Output implements Runnable {
private Resource r;
public Output(Resource r){
this.r = r;
}
@Override
public void run() {
while(true){
r.out();
}
}
}</span>
测试类:
[java] view
plain copy
print?
<span style="font-size:14px;">package com.edu.csu.syn;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
//创建资源
Resource r = new Resource();
//创建任务
Input i = new Input(r);
Output o = new Output(r);
//创建线程,执行任务
Thread t = new Thread(i);
Thread t1 = new Thread(o);
//开启线程
t.start();
t1.start();
}
}
</span>
相关文章推荐
- 关于java方法的一些东西(摘自JLS)
- [Java] 关于Java,你值得看的一些东西
- 关于线程中的一些原则行东西
- 关于java的一些东西
- Java 关于线程的一些面试题
- 关于java线程的一些特性 启动 中断 及如何退出
- 转载的关于java学习的一些东西
- 无聊时,看的一些关于java东西(持续更新)
- java关于==需要知道的一些东西
- 关于java线程、进程的一些问题
- 关于java线程的一些理解
- Android初学之关于java的一些东西
- 关于java中线程的一些总结
- 关于java学习的一些东西
- 关于JAVA-一些要记住的东西
- 关于java线程的一些了解
- 关于C++文件读写的一些东西
- 关于Matlab,C/C++和Java之间的一些想法
- Google的秘密,对Google感兴趣,所以放上来一些关于Google的东西
- 关于OpenPOP/OpenSMTP/Mail.Net的一些东西……