//线程互斥
public class Test4 {
//经验学习:要用到共同数据(包括同步锁)或共同算法的若干方法应该归到同一个类身上,这样这几体现了高内聚和程序的健壮性
//线程互斥
public static void main(String[] args) {
//(用两个线程)实现向屏幕打印两个字符串,tom jerry。
new Test4().init();
//多线程代码块中(run方法内)要做到互斥效果,需要用到同一个对象锁.
}
/**
*
* @author Administrator
* 打印字符类
*/
class OutPutToScreen{
//this 锁:
//synchronized 这个方法里的代码具有排他性
//互斥效果一定要是同一个对象,这个例子中A线程用到OutPutToScreen print对象,B
//线程也用到OutPutToScreen print对象,因此用此对象当锁,此外还可以用其他当锁,但一定要是与这两个线程无关的对象。
public synchronized void print(String string){
//如果不加synchronized则不会产生互斥效果,输出的字符串可能不完整
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
}
}
/**
* run方法里面操作的是同一个对象。因此用到当前对象锁,当前对象在被线程占用时,其他线程无法操作。
*/
public void init(){
OutPutToScreen print = new OutPutToScreen();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
print.print("thread_test");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
print.print("tom_and_jerry");
}
}
}).start();
}
}
public class Test4_1 {
public static void main(String[] args) {
//(用两个线程)实现向屏幕打印两个字符串,tom jerry。
new Test4_1().init();
}
/**
*
* @author Administrator
* 打印字符类
*/
class OutPutToScreen{
//OutPutToScreen.class 锁:
//互斥效果一定要是同一个对象,这个例子中A线程用到OutPutToScreen print对象,B
public void print(String string){
//
synchronized(OutPutToScreen.class){
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
}
}
public void print2(String string){
synchronized(OutPutToScreen.class){
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
}
}
}
public void init(){
OutPutToScreen print = new OutPutToScreen();
OutPutToScreen print2 = new OutPutToScreen();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//线程操作不同对象
print.print("thread_test");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//线程操作不同对象
print2.print("tom_and_jerry");
}
}
}).start();
}
}
public class Test4_2 {
public static void main(String[] args) {
//(用两个线程)实现向屏幕打印两个字符串,tom jerry。
new Test4_2().init();
}
/**
* @author Administrator
* 打印字符类
*/
class OutPutToScreen{
//互斥效果一定要是同一个对象
public synchronized void print(String string){
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
}
public synchronized void print2(String string){
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
}
}
public void init(){
OutPutToScreen print = new OutPutToScreen();
//下面这两个run方法里的代码要做到互斥。由于是2个不同的对象,
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//同一个对象
print.print("thread_test");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//同一个对象
print.print2("tom_and_jerry");
}
}
}).start();
}
}
public class Test4_3 {
public static void main(String[] args) {
//(用两个线程)实现向屏幕打印两个字符串,tom jerry。
new Test4_3().init();
}
/**
* @author Administrator
* 打印字符类
*/
static class OutPutToScreen{
//互斥效果一定要是同一个对象
public void print(String string){
synchronized(OutPutToScreen.class){
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
}
}
public void print2(String string){
synchronized(OutPutToScreen.class){
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
}
}
//静态方法只有跟字节码对象关联
public static void print3(String string){
synchronized(OutPutToScreen.class){
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
}
}
}
public void init(){
OutPutToScreen print = new OutPutToScreen();
//下面三个线程中的代码做到了互斥效果
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//同一个对象
print.print("thread_test");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//同一个对象
print.print2("tom_and_jerry");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//同一个对象 ,静态方法
print.print3("lilei_and_hanmeimei");
}
}
}).start();
}
}
//线程范围内共享变量
import java.util.Random;
/**
* 线程范围内的共享变量
*/
public class Test5 {
Random r = new Random();
//threadLocal放的数据就是当前线程的数据。如果遇到多个变量,则可以将这些变量封装到一个类中。(ThreadLocal<Object>)
ThreadLocal<String> threadLocal = new ThreadLocal<String>();
//ThreadLocal 实现线程范围的共享变量.(一个线程一个数据)
public static void main(String[] args) {
//单例。。。
new Test5().test();
}
public void test(){
new Thread(new AGet()).start();
new Thread(new BGet()).start();
new Thread(new CGet()).start();
}
//读数据
class AGet implements Runnable{
@Override
public void run() {
String temp = String.valueOf(r.nextInt(100));
temp = temp + "temp";
threadLocal.set(temp);
print();
}
public void print(){
System.out.println("AGet print:"+threadLocal.get());
}
}
//读数据
class BGet implements Runnable{
@Override
public void run() {
String temp = String.valueOf(r.nextInt(100));
temp = temp + "temp";
threadLocal.set(temp);
print();
}
public void print(){
System.out.println("BGet print:"+threadLocal.get());
}
}
//写数据
class CGet implements Runnable{
@Override
public void run() {
String temp = String.valueOf(r.nextInt(100));
temp = temp + "temp";
threadLocal.set(temp);
print();
}
public void print(){
System.out.println("CSet print:"+threadLocal.get());
}
}
}
//多线程之间共享数据方式
public class Test6 {
public static void main(String[] args) {
//多线程之间共享数据的方式:
//1:如果每个线程执行的代码相同,可以用同一个Runnable对象,这个Runnable对象中持有那个共享数据
TicketSell ticketSell = new TicketSell();
new Thread(ticketSell).start();
new Thread(ticketSell).start();
//2:如果每个线程执行的代码不同,这个时候需要用不同的Runnable对象,有下面方式实现
//runnable对象之间的数据共享
//--将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象,
//每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各种操作的互斥和通信。
}
static class TicketSell implements Runnable{
private int count = 10000;
/**
* 卖票
*/
public synchronized void decrement(){
//模拟
count --;
}
@Override
public void run() {
while(true){
//业务操作
}
}
}
}
//线程并发库:java.util.concurrent
<span style="color:#ff0000;">java.util.concurrent.atomic: 对于多线程操作基本数据类型的情况下。可以考虑用此包下的类.</span>
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class Test7 {
public static void main(String[] args) {
//线程并发库:java.util.concurrent
//AtomicInteger:线程安全的对整数操作的类,多个线程访问同一个整数的情况下可以考虑用这类。
//介绍对 基本数据(AtomicIntenger),
//对数组中的 基本数据(AtomicIntegerArray),
//对类中的 基本数据的操作(AtomicIntegerFieldUpdater<T>)。
AtomicInteger a = new AtomicInteger(100);
//如果a(100)==100 ,则a被赋值20,否则返回false。相当与三目运算符
boolean b = a.compareAndSet(100, 20);
System.out.println(b);//true
System.out.println("compareAndSet"+a);//20
//加1
int increment = a.incrementAndGet();
System.out.println("incrementAndGet"+increment);
//减一
int decreament = a.decrementAndGet();
System.out.println("incrementAndGet"+decreament);
//设置值为60
a.set(60);
System.out.println("set"+a);
//加50(减等于加负数)
int addresult = a.addAndGet(50);
System.out.println("addAndGet"+addresult);
}
}